数据结构-双向链表的基本操作 详解(c语言实现)

Posted 许同学。。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构-双向链表的基本操作 详解(c语言实现)相关的知识,希望对你有一定的参考价值。

1.创造一个节点,函数实现

DListNode* BuyListNode(Datetype x)
{
	DListNode*node = (DListNode*)malloc(sizeof(DListNode));
	node->date = x;
	node->next = NULL;
	node->prev = NULL;
	return node;
}

2. 初始化

DListNode* DListInit()
{
	DListNode*plist = BuyListNode(0);
	plist->date = 0;
	plist->next = plist;
	plist->prev = plist;
	return plist;
}
//既然是双向循环链表,初始化的时候,prev与next需要指向自己。

既然是双向循环链表,初始化的时候,prev与next需要指向自己。

3.判空

int DListIsEmpty(DListNode*plist)
{
	return plist->next == plist ? 1 : 0;
}

只有一个头节点的时候,链表为空。

4.头插

void DListPushFront(DListNode*plist,Datetype x)
{
	DListNode*first = plist->next;
	DListNode*newnode = BuyListNode(x);
	newnode->prev = plist;
	plist->next = newnode;
	newnode->next=first;
	first->prev = newnode;
}
//只有一个头结点时,代码也是正确的。

只有一个头节点时,代码也是正确的。

5.尾插

void DListPushBack(DListNode*plist,Datetype x)
{
	if (DListIsEmpty(plist))
	{
		return;
	}
//如果是空表的话,就与尾插这个定义矛盾了。
	DListNode*tail = plist->prev;
	DListNode*newnode = BuyListNode(x);
	tail->next = newnode;
	newnode->prev = tail;
	newnode->next = plist;
	plist->prev = newnode;
}

尾插肯定需要找尾。

6.头删

void DListPopFront(DListNode*plist)
{
	if (DListIsEmpty(plist))
	{
		return;
	}
	DListNode*first = plist->next;
	DListNode*next = first->next;
	free(first);
	first = NULL;
	plist->next = next;
	next->prev = plist;
}

一个头节点与一个节点和一个头节点与多个节点代码都是一样的。 

7.尾删

void DListPopBack(DListNode*plist)
{
	if (DListIsEmpty(plist))
	{
		return;
	}
	DListNode*tail = plist->prev;
	DListNode*tailprev = tail->prev;
	free(tail);
	tail = tailprev;
	tail->next = plist;
	plist->prev = tail;
}

 一个头节点与一个节点和一个头节点与多个节点代码都是一样的。

8.查找数据

DListNode* DListFind(DListNode*plist,Datetype x)
{
	DListNode*cur = plist->next;
	while (cur != plist)
	{
		if (cur->date == x)
		{
			return cur;
		}
		cur = cur->next;	
	}
	return NULL;
}

查找数据成功后 就返回数据的地址 。

9.在pos下一个位置插入数据

void DListInsertAfter(DListNode*pos, Datetype x)
{
	assert(pos);//保证传过来的地址不能为空
	DListNode*next = pos->next;
	DListNode*newnode = BuyListNode(x);
	pos->next = newnode;
	newnode->prev = pos;
	newnode->next = next;
	next->prev = newnode;
}

需要注意的是 pos不能为空。

10.在pos的上一个位置插入数据

void DListInsertBefore(DListNode*pos, Datetype x)
{
	assert(pos);
	DListNode*prev = pos->prev;
	DListNode*newnode = BuyListNode(x);
	prev->next = newnode;
	newnode->prev = prev;
	newnode->next = pos;
	pos->prev = newnode;
}

 一个头节点和一个有效节点时 代码也正确。

11.修改pos位置的数据

void DListModify(DListNode*pos, Datetype x)
{
	assert(pos);
	pos->date = x;
}

12.删除pos位置的数据

void DListErase(DListNode*pos)
{
	assert(pos);
	DListNode*next = pos->next;
	DListNode*prev = pos->prev;
	free(pos);
	pos = next;
	prev->next = next;
	next->prev = prev;
}

13.链表的有效长度(不包括头节点)

int DListSize(DListNode*plist)
{
	DListNode*cur = plist->next;
	int size = 0;
	while (cur != plist)
	{
		cur = cur->next;
		++size;
	}
	return size;
}

14.打印链表(测试各个接口)

void Print(DListNode*plist)
{
	DListNode*cur = plist->next;
	while (cur != plist)
	{
		printf("%3d", cur->date);
		cur = cur->next;
	}
	printf("\\n");
}

15.销毁链表

void Destory(DListNode*plist)
{
	DListNode*cur = plist->next;
	while (cur != plist)
	{
		DListNode*next = cur->next;
		free(cur);
		cur = next;
	}
	free(plist);
	plist = cur = NULL;
}
//因为这里传的是一级指针,主函数定义的phead也需要置空,防止phead成为野指针。

因为这里传的是一级指针,主函数定义的phead也需要置空,防止phead成为野指针。

16.测试

test()
{
//头插3个数据
	DListNode*phead = DListInit();
	DListPushFront(phead, 3);
	DListPushFront(phead, 2);
	DListPushFront(phead, 1);
	Print(phead);

//尾插3个数据
	DListPushBack(phead, 4);
	DListPushBack(phead, 5);
	DListPushBack(phead, 6);
	Print(phead);

//头删1个数据
	DListPopFront(phead);
	Print(phead);

//尾删1个数据
	DListPopBack(phead);
	Print(phead);

//查找数据,如果查找数据成功了,就返回数据的地址,失败,就返回空。
	DListNode* pos = DListFind(phead, 3);
	if (pos)
	{
		printf("  Date found");
		printf("\\n");
	}

//在pos下一个位置插入1个数据
	DListInsertAfter(pos, 7);
	Print(phead);

//在pos的上一个位置插入1个数据
	DListInsertBefore(pos, 8);
	Print(phead);

//将pos位置的数据改变
	DListModify(pos, 9);
	Print(phead);

//消除pos位置的数据
	DListErase(pos);
	Print(phead);

//计算出链表中的有效数字
	printf("  %d\\n",DListSize(phead));
	Destory(phead);
	phead = NULL;//防止phead成为野指针
}

 

 双向链表的基本操作就分享到这里了,谢谢你的浏览,如果这篇博文对你有帮助的话,可以点个赞,顺手再来个关注。

下期将发布与字符串函数的相关内容的文章。

 

 

 

 

 

 

 

 

 

 

 

 

以上是关于数据结构-双向链表的基本操作 详解(c语言实现)的主要内容,如果未能解决你的问题,请参考以下文章

双向循环链表增删查改C语言实现

c语言关于链表的一道题

双向链表排序c语言程序设计

双向链表排序c语言程序设计

c语言 双向链表的简单操作-创建插入删除

双向线索二叉树详解(包含C语言实现代码)