数据结构 双向链表 C语言实现

dlist.h

 1 #ifndef __dList_H
 2 #define __dlist_H
 3
 4 typedef    int Item;
 5 typedef struct Node *PNode;
 6 typedef PNode Position;
 7 /*定义节点类型*/
 8 typedef struct Node
 9 {
10     Item data; /*数据域*/
11     PNode previous; /*指向前驱*/
12     PNode next;    /*指向后继*/
13 }Node;
14
15 /*定义链表类型*/
16 typedef struct
17 {
18     PNode head; /*指向头节点*/
19     PNode tail; /*指向尾节点*/
20     int size;
21 }DList;
22
23
24 /*分配值为i的节点,并返回节点地址*/
25 Position MakeNode(Item i);
26 /*释放p所指的节点*/
27 void FreeNode(PNode p);
28 /*构造一个空的双向链表*/
29 DList* InitList();
30 /*摧毁一个双向链表*/
31 void DestroyList(DList *plist);
32 /*将一个链表置为空表,释放原链表节点空间*/
33 void ClearList(DList *plist);
34 /*返回头节点地址*/
35 Position GetHead(DList *plist);
36 /*返回尾节点地址*/
37 Position GetTail(DList *plist);
38 /*返回链表大小*/
39 int GetSize(DList *plist);
40 /*返回p的直接后继位置*/
41 Position GetNext(Position p);
42 /*返回p的直接前驱位置*/
43 Position GetPrevious(Position p);
44 /*将pnode所指节点插入第一个节点之前*/
45 PNode InsFirst(DList *plist,PNode pnode);
46 /*将链表第一个节点删除并返回其地址*/
47 PNode DelFirst(DList *plist);
48 /*获得节点的数据项*/
49 Item GetItem(Position p);
50 /*设置节点的数据项*/
51 void SetItem(Position p,Item i);
52 /*删除链表中的尾节点并返回其地址,改变链表的尾指针指向新的尾节点*/
53 PNode Remove(DList *plist);
54 /*在链表中p位置之前插入新节点S*/
55 PNode InsBefore(DList *plist,Position p,PNode s);
56 /*在链表中p位置之后插入新节点s*/
57 PNode InsAfter(DList *plist,Position p,PNode s);
58 /*返回在链表中第i个节点的位置*/
59 PNode LocatePos(DList *plist,int i);
60 /*依次对链表中每个元素调用函数visit()*/
61 void ListTraverse(DList *plist,void (*visit)());
62
63 #endif

dlist.c

  1 #include"dlist.h"
  2 #include<malloc.h>
  3 #include<stdlib.h>
  4 /*分配值为i的节点,并返回节点地址*/
  5 Position MakeNode(Item i)
  6 {
  7     PNode p = NULL;
  8     p = (PNode)malloc(sizeof(Node));
  9     if(p!=NULL)
 10     {
 11         p->data = i;
 12         p->previous = NULL;
 13         p->next = NULL;
 14     }
 15     return p;
 16 }
 17 /*释放p所指的节点*/
 18 void FreeNode(PNode p)
 19 {
 20      free(p);
 21 }
 22 /*构造一个空的双向链表*/
 23 DList * InitList()
 24 {
 25     DList *plist = (DList *)malloc(sizeof(DList));
 26     PNode head = MakeNode(0);
 27     if(plist!=NULL)
 28     {
 29         if(head!=NULL)
 30         {
 31             plist->head = head;
 32             plist->tail = head;
 33             plist->size = 0;
 34         }
 35         else
 36             return NULL;
 37     }
 38     return plist;
 39 }
 40
 41 /*摧毁一个双向链表*/
 42 void DestroyList(DList *plist)
 43 {
 44     ClearList(plist);
 45     free(GetHead(plist));
 46     free(plist);
 47 }
 48
 49 /*判断链表是否为空表*/
 50 int IsEmpty(DList *plist)
 51 {
 52     if(GetSize(plist) == 0 && GetTail(plist) == GetHead(plist))
 53         return 1;
 54     else
 55         return 0;
 56 }
 57 /*将一个链表置为空表,释放原链表节点空间*/
 58 void ClearList(DList *plist)
 59 {
 60     PNode temp,p;
 61     p = GetTail(plist);
 62     while(!IsEmpty(plist))
 63     {
 64         temp = GetPrevious(p);
 65         FreeNode(p);
 66         p = temp;
 67         plist->tail = temp;
 68         plist->size--;
 69     }
 70 }
 71
 72 /*返回头节点地址*/
 73 Position GetHead(DList *plist)
 74 {
 75     return plist->head;
 76 }
 77
 78 /*返回尾节点地址*/
 79 Position GetTail(DList *plist)
 80 {
 81     return plist->tail;
 82 }
 83
 84 /*返回链表大小*/
 85 int GetSize(DList *plist)
 86 {
 87     return plist->size;
 88 }
 89
 90 /*返回p的直接后继位置*/
 91 Position GetNext(Position p)
 92 {
 93     return p->next;
 94 }
 95
 96 /*返回p的直接前驱位置*/
 97 Position GetPrevious(Position p)
 98 {
 99     return p->previous;
100 }
101
102 /*将pnode所指节点插入第一个节点之前*/
103 PNode InsFirst(DList *plist,PNode pnode)
104 {
105     Position head = GetHead(plist);
106
107     if(IsEmpty(plist))
108         plist->tail = pnode;
109     plist->size++;
110
111     pnode->next = head->next;
112     pnode->previous = head;
113
114     if(head->next!=NULL)
115         head->next->previous = pnode;
116     head->next = pnode;
117
118     return pnode;
119 }
120
121 /*将链表第一个节点删除,返回该节点的地址*/
122 PNode DelFirst(DList *plist)
123 {
124     Position head = GetHead(plist);
125     Position p=head->next;
126     if(p!=NULL)
127     {
128         if(p==GetTail(plist))
129             plist->tail = p->previous;
130         head->next = p->next;
131         head->next->previous = head;
132         plist->size--;
133
134     }
135     return p;
136 }
137
138 /*获得节点的数据项*/
139 Item GetItem(Position p)
140 {
141     return p->data;
142 }
143
144 /*设置节点的数据项*/
145 void SetItem(Position p,Item i)
146 {
147     p->data = i;
148 }
149
150 /*删除链表中的尾节点并返回地址,改变链表的尾指针指向新的尾节点*/
151 PNode Remove(DList *plist)
152 {
153     Position p=NULL;
154     if(IsEmpty(plist))
155         return NULL;
156     else
157     {
158         p = GetTail(plist);
159         p->previous->next = p->next;
160         plist->tail = p->previous;
161         plist->size--;
162         return p;
163     }
164 }
165 /*在链表中p位置之前插入新节点s*/
166 PNode InsBefore(DList *plist,Position p,PNode s)
167 {
168     s->previous = p->previous;
169     s->next = p;
170     p->previous->next = s;
171     p->previous = s;
172
173     plist->size++;
174     return s;
175 }
176 /*在链表中p位置之后插入新节点s*/
177 PNode InsAfter(DList *plist,Position p,PNode s)
178 {
179     s->next = p->next;
180     s->previous = p;
181
182     if(p->next != NULL)
183         p->next->previous = s;
184     p->next = s;
185
186     if(p = GetTail(plist))
187         plist->tail = s;
188
189     plist->size++;
190     return s;
191 }
192
193 /*返回在链表中第i个节点的位置*/
194 PNode LocatePos(DList *plist,int i)
195 {
196     int cnt = 0;
197     Position p = GetHead(plist);
198     if(i>GetSize(plist)||i<1)
199         return NULL;
200
201     while(++cnt<=i)
202     {
203         p=p->next;
204     }
205
206     return p;
207 }
208
209 /*依次对链表中每个元素调用函数visit()*/
210 void ListTraverse(DList *plist,void (*visit)())
211 {
212     Position p = GetHead(plist);
213     if(IsEmpty(plist))
214         exit(0);
215     else
216     {
217
218         while(p->next!=NULL)
219         {
220             p = p->next;
221             visit(p->data);
222         }
223     }
224 }

test.c

 1 #include"dlist.h"
 2 #include<stdio.h>
 3
 4 void print(Item i)
 5 {
 6     printf("数据项为%d \n",i);
 7 }
 8 int main()
 9 {
10     DList *plist = NULL;
11     PNode p = NULL;
12
13     plist = InitList();
14     p = InsFirst(plist,MakeNode(1));
15     InsBefore(plist,p,MakeNode(2));
16     InsAfter(plist,p,MakeNode(3));
17
18     printf("p前驱位置的值为%d\n",GetItem(GetPrevious(p)));
19     printf("p位置的值为%d\n",GetItem(p));
20     printf("p后继位置的值为%d\n",GetItem(GetNext(p)));
21
22
23     printf("遍历输出各节点数据项:\n");
24     ListTraverse(plist,print);
25     printf("除了头节点该链表共有%d个节点\n",GetSize(plist));
26     FreeNode(DelFirst(plist));
27     printf("删除第一个节点后重新遍历输出为:\n");
28     ListTraverse(plist,print);
29     printf("除了头节点该链表共有%d个节点\n",GetSize(plist));
30     DestroyList(plist);
31     printf("链表已被销毁\n");
32 }

运行结果:

[[email protected] 02.Doublylinklist]$ gcc test.c dlist.c dlist.h -o test
[[email protected] 02.Doublylinklist]$ tree -L 2
.
├── dlist.c
├── dlist.h
├── test
├── test.c
└── \345\217\214\345\220\221\351\223\276\350\241\250
    ├── bin
    ├── obj
    ├── \345\217\214\345\220\221\351\223\276\350\241\250.cbp
    ├── \345\217\214\345\220\221\351\223\276\350\241\250.depend
    └── \345\217\214\345\220\221\351\223\276\350\241\250.layout

3 directories, 7 files
[[email protected] 02.Doublylinklist]$ ./test
p前驱位置的值为2
p位置的值为1
p后继位置的值为3
遍历输出各节点数据项:
数据项为2
数据项为1
数据项为3
除了头节点该链表共有3个节点
删除第一个节点后重新遍历输出为:
数据项为1
数据项为3
除了头节点该链表共有2个节点
链表已被销毁
[[email protected] 02.Doublylinklist]$ ^

转自 -- http://blog.csdn.net/hopeyouknow/article/details/6716177

时间: 2024-11-11 19:32:37

数据结构 双向链表 C语言实现的相关文章

数据结构算法C语言实现(十)--- 3.3栈与递归的实现

一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二.CPP文件 1 //3_3.cpp 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-8 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 54 9

数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚,所以很多需要自己揣摩.这也体现了算法和程序设计语言的特点,算法更侧重本质的描述,而任何编程语言都要照顾到实现的细节以及数据类型等语法方面的需求. 表达式求值: [编码中....] 二.头文件 迷宫求解: 1 //3_2_maze.h 2 /** 3 author:zhaoyu 4 email:[em

数据结构算法C语言实现(七)--- 3.1 的线性实现及应用举例

一.简述 栈,LIFO.是操作受限的线性表,和线性表一样有两种存储表示方法.下面以顺序存储为例,实现. 二.ADT 暂无. 三.头文件 1 //3_1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-7 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 46 9 10 #ifndef _3_1_H_ 11 #define _3_1_H_ 12

数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树

一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈及相关操作是第三章实现的,但数据类型做了更改. 二.头文件 1 //3_1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-7 6 note:realize my textbook <<数据结构(C语言版)>&g

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

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

数据结构算法C语言实现(十二)--- 3.4循环队列&amp;队列的顺序表示和实现

一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 1 //3_4_part1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-9 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 64 9 #include <cstdio

数据结构算法C语言实现(十一)--- 3.4队列的链式表示和实现

一.简介 FIFO. 二.头文件 1 //3_4_part1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-9 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 61 9 #include <cstdio> 10 #include "head.h" 11 #define QElemType int 12 //

数据结构算法C语言实现(一)---2.3线性表的顺序表示和实现

注意: 虽然是用C语言实现,但是考虑到使用了一个C++的特性----引用以简化代码,所以所有的代码均以cpp作为后缀,用g++编译(以后不做说明). g++版本: 一.简述 本节主要讲述线性表的顺序实现,主要操作包括建表,插入元素,删除元素,查找元素,合并表等操作,根据书中伪代码编写了C语言,使用int类型进行了测试,需要注意的是查找元素时使用了函数指针,C语言初学者不易理解,可查阅相关书籍学习. 二.头文件 1 //head.h 2 /** 3 My Code 4 */ 5 #include

数据结构成为小语言

面向语言的开发并不一定意味着,一定要自己开发解析器或编译器.这就是说,我们将在下一章学习创建解析器,然后,把这样的解析器和本章介绍的方法照结合起来,去构建一个简单的编译器.可以通过创建数据结构和函数或模块,就能够做很多事,数据结构描述了准备做什么,而函数或模块定义了如何解释结构. 几乎可以用任何语言创建数据结构来表示一个程序,但是 F# 更适合.F# 的文字列表和数组很容易定义,不要求庞大的类型注解:它的联合类型能够创建结构,来表达相关的概念,但却不一定要包含相同类型的数据,可以用它来创建树型结