C语言一个双向链表的实现

来源:互联网 发布:c语言面试常见问题 编辑:程序博客网 时间:2024/06/06 03:39

首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下:

#ifndef DList_H#define DList_Htypedef  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;}elsereturn 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;elsereturn 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");}