您的位置:首页 > 编程语言 > C语言/C++

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

2014-09-25 15:02 295 查看
首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下:

[cpp] view
plaincopy

#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内容如下:

[cpp] view
plaincopy

#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内容如下:

[cpp] view
plaincopy

#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");

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: