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

首先编写头文件,头文件里做相关的定义和声明,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
#include
/*分配值为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
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");
}


 

 

你可能感兴趣的:(算法,C/C++编程)