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

来源:互联网 发布:ios多线程编程运用 编辑:程序博客网 时间:2024/06/06 05:16


首先编写头文件,头文件里做相关的定义和声明,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.c内容如下:

#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前驱位置的值为%dn",GetItem(GetPrevious(p)));      printf("p位置的值为%dn",GetItem(p));      printf("p后继位置的值为%dn",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");  }  


原创粉丝点击