首页 > 代码库 > 双向链表(c语言版)

双向链表(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 =http://www.mamicode.com/ 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 }