当前位置:网站首页>使用C语言实现双向链表(带头结点)
使用C语言实现双向链表(带头结点)
2022-08-09 08:58:00 【Keep_Trying_Go】
目录
1.双链表
相对于单链表来说就是多一个前驱的指针prior,指向前一个节点(主要是为了方便删除和插入)。
注:由于之前的实现的单链表总是会遇到一种情况就是,如果要删除当前的节点p的话,那么只能通过一种技巧的方式计算交换值;但是如果是需要进行更加复杂的操作的话,就会比较麻烦,可能还需要辅助的指针r来指向当前节点的前驱,这会给程序写起来和理解起来带来不便,所以为了实现当前节点能够访问前驱节点,那么提出了双链表的概念。
2.双链表的相关操作
(1)数据结构的定义
#include<stdlib.h>
#include<stdio.h>
#define MAXSIZE 10
typedef int ElemType;
typedef struct DNode {
ElemType data;
struct DNode*prior,*next;
}DNode,*DLinkList;
//清单列表
void MenuLinkList(){
printf("-------------1.插入操作-------------\n");
printf("-------------2.定位插入操作---------\n");
printf("-------------3.按序查找操作---------\n");
printf("-------------4.按值查找操作---------\n");
printf("-------------5.定位删除操作---------\n");
printf("-------------6.按值删除元素---------\n");
printf("-------------7.删除整个表元素节点---\n");
printf("-------------8.表的长度-------------\n");
printf("-------------9.打印操作-------------\n");
printf("-------------10.结束操作-------------\n");
}
(2)初始化和销毁
//初始化操作
void InitDLinkList(DLinkList&L){
L=(DNode*)malloc(sizeof(DNode));
if(L==NULL){
printf("申请空间失败!\n");
return ;
}
L->prior=NULL;
L->next=NULL;
printf("申请空间成功!\n");
}
//销毁表(头节点不销毁)
DNode* DestryDLinkList(DNode*p,DLinkList&L,int flag=9){
//从尾部开始删除节点
DNode*r=p;
while(r!=L){
DNode*s=r;
r=r->prior;
r->next=s->next;
free(s);
}
//如果是结束操作的话,直接将头节点释放
if(flag==10){
free(L);
L=NULL;
}
return r;
}
这里的销毁操作主要是从最后节点开始进行删除,更加的方便,如果从头结点开始删除的话,需要判断的条件更多,相对麻烦一点,所以采用这种方法。读者自己可以实现从前往后的删除操作。
(3)判断空和表的长度
//判空
bool Empty(DLinkList L){
if(L->next==NULL){
return true;
}else{
return false;
}
}
//表的长度
int DLinkListLength(DLinkList L){
int len=0;
DNode*p=L->next;
while(p!=NULL){
len++;
p=p->next;
}
return len;
}
(4)节点的后插操作
//节点的插入操作(后插)
DNode* InsertDLinkList(DNode*p,ElemType e){
if(p==NULL){
printf("插入的节点不合法!\n");
return NULL;
}
DNode*s=(DNode*)malloc(sizeof(DNode));
s->data=e;
s->next=p->next;
p->next=s;
s->prior=p;
printf("插入节点成功!\n");
return s;
}
//在第i个位置插入节点
void InsertIDLinkList(DLinkList&L,int i,ElemType e){
DNode*p=FindDNode(L,i);
//如果是插入到尾节点
if(p->next==NULL){
InsertDLinkList(p,e);
return ;
}
//插入到中间的节点
if(p!=NULL){
DNode*s=(DNode*)malloc(sizeof(DNode));
s->data=e;
s->next=p->next;
p->next->prior=s;
p->next=s;
s->prior=p;
printf("插入节点成功!\n");
return ;
}
}
(5)按序查找第i个节点和按值查找节点
//查找第i个位序的节点
DNode*FindDNode(DLinkList L,int i){
if(L==NULL){
printf("表为空!\n");
return NULL;
}
if(i<0||i>DLinkListLength(L)){
printf("查找的位置不正确!\n");
return NULL;
}
int j=1;
DNode*p=L->next;
while(p!=NULL&&j<i){
p=p->next;
j++;
}
return p;
}
//按值查找操作
DNode*FindDElem(DLinkList L,ElemType e){
if(L==NULL){
printf("表为空!\n");
return NULL;
}
DNode*p=L->next;
while(p->data!=e){
p=p->next;
}
return p;
}
(6)定位删除和按序删除
//定位删除节点
void DeleteDLNode(DLinkList&L,int i,ElemType&e){
DNode*p=FindDNode(L,i);
e=p->data;
//如果是尾节点直接删除
if(p->next==NULL){
p->prior->next=p->next;
free(p);
return ;
}
if(p!=NULL){
DNode*s=p;
p->prior->next=s->next;
p->next->prior=s->prior;
free(s);
return ;
}
}
//按值删除
void DeleteDElem(DLinkList&L,ElemType e){
DNode*p=FindDElem(L,e);
//如果是尾节点直接删除
if(p->next==NULL){
p->prior->next=p->next;
free(p);
return ;
}
if(p!=NULL){
DNode*s=p;
p->prior->next=s->next;
p->next->prior=s->prior;
free(s);
return ;
}
}
(7)打印操作
//打印
void PrintDLinkList(DLinkList L){
DNode*p=L->next;
while(p!=NULL){
printf("%d\t",p->data);
p=p->next;
}
printf("\n");
}
(8)主函数
int main(){
DLinkList L;
InitDLinkList(L);
//对顺序表进行插入操作
ElemType x;
int flag=-1;
DNode*p=L;
//各种操作
while(1) {
int i=0;
ElemType e=0;
MenuLinkList();
printf("请输入操作: ");
scanf("%d",&flag);
int len=0;
DNode*s;
switch(flag){
case 1:
printf("请输入元素(-1_end): ");
scanf("%d",&x);
while(x!=-1) {
p=InsertDLinkList(p,x);
printf("请输入元素(-1_end): ");
scanf("%d",&x);
}
break;
case 2:
printf("请输入元素插入位置: \n");
scanf("%d",&i);
printf("请输入元素: ");
scanf("%d",&x);
InsertIDLinkList(L,i,x);
break;
case 3:
printf("请输入查找元素位置: ");
scanf("%d",&i);
s=FindDNode(L,i);
if(s!=NULL){
printf("查找的元素为 = %d\n",s->data);
}
break;
case 4:
printf("请输入要查找的值: ");
scanf("%d",&x);
s=FindDElem(L,x);
if(s!=NULL){
printf("查找的元素存在!\n");
}else{
printf("查找的元素不存在!\n");
}
break;
case 5:
printf("请输入删除的定位位置: ");
scanf("%d",&i);
DeleteDLNode(L,i,e);
printf("删除的元素为 = %d\n",e);
break;
case 6:
printf("请输入要删除的元素: ");
scanf("%d",&e);
DeleteDElem(L,e);
break;
case 7:
p=DestryDLinkList(p,L);
printf("删除成功!\n");
break;
case 8:
len=DLinkListLength(L);
printf("表的长度 = %d\n",len);
break;
case 9:
PrintDLinkList(L);
break;
default:
DestryDLinkList(p,L,flag);
printf("结束操作\n");
}
if(flag==10){
break;
}
}
return 0;
}
(9)测试
边栏推荐
猜你喜欢
随机推荐
verilog独热码实现译码MIPS指令集
RESTful
STM32 如何知道FLASH的使用情况
【LeetCode每日一题】——225.用队列实现栈
sizeof 结构体问题
leetcode 37. 解数独 (困难)
requests之数据解析Xpath介绍
解决iframe跳转时父页面仍然存在的问题
Shell编程之正则表达式
leetcode 36. 有效的数独(模拟题)
Calendar类和Date类转换时区 && 部分时区城市列表
Redis redis 】 【 the expiration of listening
The embedded serial port interrupt can only receive one byte
define 可变参数定义
无符号整数文法和浮点数文法
【KD】2022 KDD Compressing Deep Graph Neural Networks via Adversarial Knowledge Distillation
Tencent cloud server is modified to root login to install pagoda panel
正则表达式基础介绍
[V&N2020 公开赛]内存取证
makefile - 学习小结