双向链表(c语言版)

为了得到一个简洁的C语言实现的双向链表,本篇参照数据结构书籍对双向链表的做了一些修改,内容有:

  1.合并分离的头文件和实现文件,认识更为直观;

  2.修改函数名和变量名,更贴近自身的理解;

  3.删除了返回首节点、尾节点等功能更为单一的函数,留下其主干。

实现思路:

  1.定义一个双向链表

  2.进行初始化工作:调用initList(),构造一个空的双向链表

 

  3.执行增删改查等操作(节点操作) 

 *插入时注意:封装成节点

   

  1 /*双向链表实现代码*/
  2 #include<malloc.h>  
  3 #include<stdlib.h>  
  4 #include<stdio.h>
5 6 typedef struct ListNode * PNode; 7 /*定义列表节点类型*/ 8 typedef struct ListNode 9 { 10 int data; /*数值*/ 11 PNode pred; /*前驱*/ //struct ListNode* pred;(可以) 12 PNode succ; /*后继*/ //ListNode* pred;(不可以) 13 }ListNode; 14 /*定义链表类型*/ 15 typedef struct List 16 { 17 int size; /*规模*/ 18 PNode header; /*头哨兵*/ 19 PNode trailer; /*尾哨兵*/ 20 }List; 21 22 /*构造值为i的节点,并返回节点地址*/ 23 PNode makeNode(int i); 24 25 /*初始化:构造一个空的双向链表*/ 26 List* initList(); 27 28 /*摧毁一个双向链表*/ 29 void destroyList(List *plist); 30 31 /*将一个链表置为空表,释放原链表节点空间*/ 32 void clearList(List *plist); 33 34 /*将pnode作为首节点插入*/ 35 PNode insertAsFirst(List *plist,PNode pnode); 36 37 /*将链表首节点节点删除,并返回其地址*/ 38 PNode deleteFirst(List *plist); 39 40 /*删除链表中的末节点并返回其地址*/ 41 PNode listRemove(List *plist); 42 43 /*在链表中p位置之前插入新节点S*/ 44 PNode insertBefore(List *plist,PNode p,PNode s); 45 46 /*在链表中p位置之后插入新节点s*/ 47 PNode insertAfter(List *plist,PNode p,PNode s); 48 49 /*返回在链表中第i个节点的位置*/ 50 PNode locatePos(List *plist,int i); 51 52 /*遍历列表中元素:调用函数visit()*/ 53 void listTraverse(List *plist,void (*visit)()); 54 55 /*构造值为i的节点,并返回节点地址*/ 56 PNode makeNode(int i) 57 { 58 PNode p = (PNode)malloc(sizeof(ListNode)); 59 p->data = i; 60 p->pred = NULL; 61 p->succ = NULL; 62 63 return p; 64 } 65 66 /*初始化:构造一个空的双向链表*/ 67 List * initList() 68 { 69 List *plist = (List *)malloc(sizeof(List)); 70 plist->header = makeNode(0);//创建头哨兵节点 71 plist->trailer = makeNode(0);//创建尾哨兵节点 72 plist->header->succ = plist->trailer; 73 plist->trailer->pred = plist->header; 74 75 plist->size = 0;//记录规模 76 return plist; 77 } 78 79 /*摧毁一个双向链表*/ 80 void destroyList(List *plist) 81 { 82 //释放节点 83 clearList(plist); //先将一个列表置为空表,即释放表内节点 84 free(plist->header); free(plist->trailer);//再释放头尾哨兵节点 85 //释放链表 86 free(plist); 87 } 88 89 /*判断链表是否为空表*/ 90 int isEmpty(List *plist) 91 { 92 if((plist->size==0) || plist->header->succ == plist->trailer) 93 return 1; 94 else 95 return 0; 96 } 97 98 /*将一个链表置为空表,释放原链表节点空间*/ 99 void clearList(List *plist) 100 { 101 PNode temp; 102 while(!isEmpty(plist)) 103 { 104 PNode p=plist->header->succ; 105 temp = p->succ; 106 free(p); 107 plist->header->succ = temp; 108 plist->size--; 109 } 110 } 111 112 /*将pnode作为首节点插入,返回该节点的地址*/ 113 PNode insertAsFirst(List *plist,PNode pnode) 114 { 115 PNode temp = plist->header->succ;//暂存header的后继结点 116 117 temp->pred=pnode; plist->header->succ = pnode; 118 pnode->pred = plist->header; pnode->succ=temp; 119 120 plist->size++; 121 return pnode; 122 } 123 124 /*将链表第一个节点删除,返回该节点的地址*/ 125 PNode deleteFirst(List *plist) 126 { 127 PNode p=plist->header->succ; 128 129 p->succ->pred = p->pred; 130 p->pred->succ = p->succ; 131 132 plist->size--; 133 return p; 134 } 135 136 /*删除链表中的末节点,并返回该节点地址*/ 137 PNode listRemove(List *plist) 138 { 139 PNode p=plist->trailer->pred; 140 141 p->succ->pred = p->pred; 142 p->pred->succ = p->succ; 143 144 plist->size--; 145 return p; //在main中释放 146 } 147 148 /*在链表中p位置之前插入新节点s*/ 149 PNode insertBefore(List *plist,PNode p,PNode s) 150 { 151 s->pred = p->pred; s->succ = p; 152 p->pred->succ = s; p->pred = s; 153 154 plist->size++; 155 return s; 156 } 157 158 /*在链表中p位置之后插入新节点s*/ 159 PNode insertAfter(List *plist,PNode p,PNode s) 160 { 161 s->succ = p->succ; s->pred = p; 162 p->succ->pred = s; p->succ = s; 163 164 plist->size++; 165 return s; 166 } 167 168 /*返回在链表中第i个节点的位置*/ 169 PNode locatePos(List *plist,int i) 170 { 171 int cnt = 0; 172 PNode p = plist->header; 173 if(i>(plist->size)||i<1) 174 return NULL; 175 176 while(++cnt<=i) 177 { 178 p=p->succ; 179 } 180 181 return p; 182 } 183 184 /*遍历列表中元素:调用函数visit()*/ 185 void listTraverse(List *plist,void (*visit)()) 186 { 187 PNode p = plist->header; 188 if(isEmpty(plist)) 189 return; 190 else 191 { 192 while(p->succ != plist->trailer) 193 { 194 p = p->succ; 195 visit(p->data); 196 } 197 } 198 } 199 200 201 void print(int i) 202 { 203 printf("数据项为%d \n",i); 204 } 205 main() 206 { 207 List *plist = NULL; 208 PNode p = NULL; 209 210 plist = initList(); 211 p = insertAsFirst(plist,makeNode(1)); 212 insertBefore(plist,p,makeNode(2)); 213 insertAfter(plist,p,makeNode(3)); 214 215 printf("p前驱位置的值为%d\n",p->pred->data); 216 printf("p位置的值为%d\n",p->data); 217 printf("p后继位置的值为%d\n",p->succ->data); 218 219 220 printf("遍历输出各节点数据项:\n"); 221 listTraverse(plist,print); 222 printf("除了头节点该链表共有%d个节点\n",plist->size); 223 free(deleteFirst(plist)); 224 printf("删除第一个节点后重新遍历输出为:\n"); 225 listTraverse(plist,print); 226 printf("除了头节点该链表共有%d个节点\n",plist->size); 227 destroyList(plist); 228 printf("链表已被销毁\n"); 229 }

 

转载于:https://www.cnblogs.com/ackhan/p/3774693.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值