双向链表
来源:http://blog.csdn.net/hopeyouknow/article/details/6716177
首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下:
- #ifndef DList_H
- #define DList_H
- typedef int Item;
- typedef struct Node * PNode;
- typedef PNode Position;
- /*定义节点类型*/
- typedef struct Node
- {
- Item data; /*数据域*/
- PNode previous; /*指向前驱*/
- PNode next; /*指向后继*/
- }Node;
- /*定义链表类型*/
- typedef struct
- {
- PNode head; /*指向头节点*/
- PNode tail; /*指向尾节点*/
- int size;
- }DList;
- /*分配值为i的节点,并返回节点地址*/
- Position MakeNode(Item i);
- /*释放p所指的节点*/
- void FreeNode(PNode p);
- /*构造一个空的双向链表*/
- DList* InitList();
- /*摧毁一个双向链表*/
- void DestroyList(DList *plist);
- /*将一个链表置为空表,释放原链表节点空间*/
- void ClearList(DList *plist);
- /*返回头节点地址*/
- Position GetHead(DList *plist);
- /*返回尾节点地址*/
- Position GetTail(DList *plist);
- /*返回链表大小*/
- int GetSize(DList *plist);
- /*返回p的直接后继位置*/
- Position GetNext(Position p);
- /*返回p的直接前驱位置*/
- Position GetPrevious(Position p);
- /*将pnode所指节点插入第一个节点之前*/
- PNode InsFirst(DList *plist,PNode pnode);
- /*将链表第一个节点删除并返回其地址*/
- PNode DelFirst(DList *plist);
- /*获得节点的数据项*/
- Item GetItem(Position p);
- /*设置节点的数据项*/
- void SetItem(Position p,Item i);
- /*删除链表中的尾节点并返回其地址,改变链表的尾指针指向新的尾节点*/
- PNode Remove(DList *plist);
- /*在链表中p位置之前插入新节点S*/
- PNode InsBefore(DList *plist,Position p,PNode s);
- /*在链表中p位置之后插入新节点s*/
- PNode InsAfter(DList *plist,Position p,PNode s);
- /*返回在链表中第i个节点的位置*/
- PNode LocatePos(DList *plist,int i);
- /*依次对链表中每个元素调用函数visit()*/
- void ListTraverse(DList *plist,void (*visit)());
- #endif
接下来逐个实现其功能,DList.c内容如下:
- #include"DList.h"
- #include<malloc.h>
- #include<stdlib.h>
- /*分配值为i的节点,并返回节点地址*/
- Position MakeNode(Item i)
- {
- PNode p = NULL;
- p = (PNode)malloc(sizeof(Node));
- if(p!=NULL)
- {
- p->data = i;
- p->previous = NULL;
- p->next = NULL;
- }
- return p;
- }
- /*释放p所指的节点*/
- void FreeNode(PNode p)
- {
- free(p);
- }
- /*构造一个空的双向链表*/
- DList * InitList()
- {
- DList *plist = (DList *)malloc(sizeof(DList));
- PNode head = MakeNode(0);
- if(plist!=NULL)
- {
- if(head!=NULL)
- {
- plist->head = head;
- plist->tail = head;
- plist->size = 0;
- }
- else
- return NULL;
- }
- return plist;
- }
- /*摧毁一个双向链表*/
- void DestroyList(DList *plist)
- {
- ClearList(plist);
- free(GetHead(plist));
- free(plist);
- }
- /*判断链表是否为空表*/
- int IsEmpty(DList *plist)
- {
- if(GetSize(plist)==0&&GetTail(plist)==GetHead(plist))
- return 1;
- else
- return 0;
- }
- /*将一个链表置为空表,释放原链表节点空间*/
- void ClearList(DList *plist)
- {
- PNode temp,p;
- p = GetTail(plist);
- while(!IsEmpty(plist))
- {
- temp = GetPrevious(p);
- FreeNode(p);
- p = temp;
- plist->tail = temp;
- plist->size--;
- }
- }
- /*返回头节点地址*/
- Position GetHead(DList *plist)
- {
- return plist->head;
- }
- /*返回尾节点地址*/
- Position GetTail(DList *plist)
- {
- return plist->tail;
- }
- /*返回链表大小*/
- int GetSize(DList *plist)
- {
- return plist->size;
- }
- /*返回p的直接后继位置*/
- Position GetNext(Position p)
- {
- return p->next;
- }
- /*返回p的直接前驱位置*/
- Position GetPrevious(Position p)
- {
- return p->previous;
- }
- /*将pnode所指节点插入第一个节点之前*/
- PNode InsFirst(DList *plist,PNode pnode)
- {
- Position head = GetHead(plist);
- if(IsEmpty(plist))
- plist->tail = pnode;
- plist->size++;
- pnode->next = head->next;
- pnode->previous = head;
- if(head->next!=NULL)
- head->next->previous = pnode;
- head->next = pnode;
- return pnode;
- }
- /*将链表第一个节点删除,返回该节点的地址*/
- PNode DelFirst(DList *plist)
- {
- Position head = GetHead(plist);
- Position p=head->next;
- if(p!=NULL)
- {
- if(p==GetTail(plist))
- plist->tail = p->previous;
- head->next = p->next;
- head->next->previous = head;
- plist->size--;
- }
- return p;
- }
- /*获得节点的数据项*/
- Item GetItem(Position p)
- {
- return p->data;
- }
- /*设置节点的数据项*/
- void SetItem(Position p,Item i)
- {
- p->data = i;
- }
- /*删除链表中的尾节点并返回地址,改变链表的尾指针指向新的尾节点*/
- PNode Remove(DList *plist)
- {
- Position p=NULL;
- if(IsEmpty(plist))
- return NULL;
- else
- {
- p = GetTail(plist);
- p->previous->next = p->next;
- plist->tail = p->previous;
- plist->size--;
- return p;
- }
- }
- /*在链表中p位置之前插入新节点s*/
- PNode InsBefore(DList *plist,Position p,PNode s)
- {
- s->previous = p->previous;
- s->next = p;
- p->previous->next = s;
- p->previous = s;
- plist->size++;
- return s;
- }
- /*在链表中p位置之后插入新节点s*/
- PNode InsAfter(DList *plist,Position p,PNode s)
- {
- s->next = p->next;
- s->previous = p;
- if(p->next != NULL)
- p->next->previous = s;
- p->next = s;
- if(p = GetTail(plist))
- plist->tail = s;
- plist->size++;
- return s;
- }
- /*返回在链表中第i个节点的位置*/
- PNode LocatePos(DList *plist,int i)
- {
- int cnt = 0;
- Position p = GetHead(plist);
- if(i>GetSize(plist)||i<1)
- return NULL;
- while(++cnt<=i)
- {
- p=p->next;
- }
- return p;
- }
- /*依次对链表中每个元素调用函数visit()*/
- void ListTraverse(DList *plist,void (*visit)())
- {
- Position p = GetHead(plist);
- if(IsEmpty(plist))
- exit(0);
- else
- {
- while(p->next!=NULL)
- {
- p = p->next;
- visit(p->data);
- }
- }
- }
接下来进行测试,Test.h内容如下:
- #include"DList.h"
- #include<stdio.h>
- void print(Item i)
- {
- printf("数据项为%d \n",i);
- }
- main()
- {
- DList *plist = NULL;
- PNode p = NULL;
- plist = InitList();
- p = InsFirst(plist,MakeNode(1));
- InsBefore(plist,p,MakeNode(2));
- InsAfter(plist,p,MakeNode(3));
- printf("p前驱位置的值为%d\n",GetItem(GetPrevious(p)));
- printf("p位置的值为%d\n",GetItem(p));
- printf("p后继位置的值为%d\n",GetItem(GetNext(p)));
- printf("遍历输出各节点数据项:\n");
- ListTraverse(plist,print);
- printf("除了头节点该链表共有%d个节点\n",GetSize(plist));
- FreeNode(DelFirst(plist));
- printf("删除第一个节点后重新遍历输出为:\n");
- ListTraverse(plist,print);
- printf("除了头节点该链表共有%d个节点\n",GetSize(plist));
- DestroyList(plist);
- printf("链表已被销毁\n");
- }
微信公众号:
猿人谷
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。