双向链表(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 }

双向链表(c语言版),布布扣,bubuko.com

时间: 2024-08-06 20:07:34

双向链表(c语言版)的相关文章

双向链表-C语言版

源文件部分: #include<stdio.h> #include<malloc.h> #include<string.h> typedef int Elemtype; #include"DList.h" int main() { Dlnode head=NULL; instruction(head); return 0; } 头文件部分: typedef struct DLnode { Elemtype data; struct DLnode *p

《数据结构-C语言版》(严蔚敏,吴伟民版)课本源码+习题集解析使用说明

先附上文档归类目录: 课本源码合辑  链接??? <数据结构>课本源码合辑 习题集全解析  链接??? <数据结构题集>习题解析合辑 博主有话说: 01.自学编程,难免思路阻塞,所以从今天起,我(StrayedKing)决定在本博客陆续更新严蔚敏,吴伟民版<数据结构-C语言版>各章节的课本源码和配套习题集答案解析,目的是为了整理数据结构中的知识点,并与网友交流意见,集思广益,共同进步.        ★注★ 左侧随笔分类下用两个栏目:<课本源码>.<习

人事管理系统 c语言版

int menu(){ printf("请按提示输入完成操作!\n"); printf("1.查询员工信息\n"); printf("2.统计员工数量\n"); printf("3.录入员工信息\n"); printf("4.删除员工信息\n"); printf("5.按id排序所有员工\n"); printf("6.打印所有员工信息\n"); printf(&quo

排序算法总结(C语言版)

1.    插入排序 1.1     直接插入排序 1.2     Shell排序 2.    交换排序 2.1     冒泡排序 2.2     快速排序 3.    选择排序 3.1     直接选择排序 3.2     堆排序 4.    归并排序 4.1     二路归并排序 4.2     自然合并排序 5.    分布排序 5.1     基数排序 1.插入排序 1.1      直接插入排序 将已排好序的部分num[0]~num[i]后的一个元素num[i+1]插入到之前已排好序的

51系列小型操作系统精髓 简单实现8 C语言版待改进

使用keil4  ,代码Code Optimization:0   运行OK 可运行8个任务 Program Size: data=21.0 xdata=0 code=401  (包括2个示例变量,未优化) 任务从中断处切换,在定时时间到后从定时中断中切换回来. 待改进地方 1.手动优化汇编程序 2. 重入问题 3.参数进函数和时中断的保护问题 #include "STC12C5A.H" #define TIMER_RELOAD()  {TL0=0x00;TH0=0xC4;}//使能T

51系列小型操作系统精髓 简单实现11 C语言版优化后说明(有图)

/* CRTOS 实时可剥夺型内核 1.任务不用预加载,不用预定义.任务调用时加载,可删除(退出死循环即可) 2.单位轮转查询时间由晶振和定时器初始化决定.在这里为10ms 3.定时时间为[ time*单位轮转查询时间 ] ,其中time为 rtos_wait(time)中time. 4.可运行多个任务[自定义] 5.任务从rtos_wait()处切换,在定时时间到后从定时中断中切换回来,任务执行后,回到中断,再从中断回到主程序. */ #include "STC12C5A.H" #d

51系列小型操作系统精髓 简单实现7 C语言版待改进

#include "STC12C5A.H" #define TIMER_RELOAD()  {TL0=0x00;TH0=0xC4;}//使能T/C  初始10ms #define MAX_TASKS 2 //任务槽最大个数. unsigned char idata task_stack[MAX_TASKS][2];//任务堆栈.  PC指针为16位,需2个字节task_stack[][0]L  task_stack[][1]H. unsigned char idata task_tim

2048小游戏(C语言版)

1 #include <climits> 2 #include <cstdio> 3 #include <cstring> 4 #include <stack> 5 #include <string> 6 #include <map> 7 #include <vector> 8 #include <cmath> 9 10 11 /* 12 玩法说明:编译运行后,输入一个整数n,表示自己想玩的游戏中是n*n的表格

(续)线性表之双向链表(C语言实现)

在前文实现单向链表的基本操作下,本文实现 双向链表的基本操作. 双向链表与单链表差异,是双向链表结点中有前向指针和后向指针. 所以在插入和删除新结点元素时候不见要考虑后向指针还要考虑 前向指针. 以下是双向链表的C代码: #include<stdio.h> typedef struct node { int data; struct node *next; struct node *prior }Node; //链表的初始化 Node* InitList(int number) { int i