当前位置:网站首页>【双链表增删查改接口的实现】

【双链表增删查改接口的实现】

2022-08-09 21:35:00 努力上进呀

hello 大家好呀,今天向大家分享的是双链表增删查改接口的实现,如果哪里有什么不对的地方希望各位佬帮忙指正一下。

这次博主分享的是带头双向循环链表:

结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而 简单了,后面我们代码实现了就知道了。
 
17c901c6679047498ea79efe5ef81a51.png

目录

 

 

1 初始化链表

2 尾插和头插

 3 尾删和头删

4 查找和查插和查删)

5 释放


 

 

1 初始化链表

ListNode* ListNodeCreat(LTDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode)
	{
		newnode->data = x;
		newnode->next = NULL;
		newnode->prev = NULL;
	}
	return newnode;
}


ListNode* InitList(void)
{
	ListNode* phead = ListNodeCreat(1);
	phead->next = phead;
	phead->prev = phead;
	return phead;
}

链表的初始化我们将phead的prev与next都指向phead,这里的处理在后面有一些妙用,这里就先不说了,头结点这里是通过返回值实现的,当然,通过二级指针也可以,效果都差不多。头结点是不存储数据的,只是充当哨兵的作用。

2 尾插和头插

尾插的具体代码:

void ListPushBack(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListNode* tail = phead->prev;
	ListNode* newtail = ListNodeCreat(x);
	tail->next = newtail;
	newtail->prev = tail;
	newtail->next = phead;
	phead->prev = newtail;

	//ListInsert(phead, x);
}

尾插的实现很简单,都能够看懂。在这里我们就可以看见将phead的prev与next都指向phead的好处了,就算phead后面一个结点都没有依然能够处理,这样写代码就很简练了。

头插的具体代码:

void ListPushFront(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListNode* next = phead->next;
	ListNode* newnode = ListNodeCreat(x);
	phead->next = newnode;
	newnode->prev = phead;
	newnode->next = next;
	next->prev = newnode;

	//ListInsert(phead->next, x);
}

头插的实现也比较简单,其实把图画好就能够解决问题,这里当头结点后面一个结点都没有也能够处理。

来看看效果:

 c9c80d941d854cd3a19a8520e82b4e04.png

 3 尾删和头删

尾删和头删对于双链表来说也比较简单,这里就放在一起写了:

void ListPopBack(ListNode* phead)
{
	assert(phead);
	ListNode* tail = phead->prev;
	ListNode* prev = tail->prev;
	prev->next = phead;
	phead->prev = prev;
	free(tail);

	//ListErase(phead->prev);
}

void ListPopFront(ListNode* phead)
{
	assert(phead);
	ListNode* next = phead->next->next;
	free(phead->next);
	phead->next = next;
	next->prev = phead;

	//ListErase(phead->next);
	
}

按部就班的写,注意不要写漏了就ok了。

效果:

abb8f8e714c2426eb15b4927d5cda36a.png

 

4 查找和查插和查删)

查找的具体代码:

ListNode* ListFind(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
	}
	return NULL;
}

与单链表一样,这个也可以改变数据:

03276fe8cdc8427f831cabe865855482.png

 查插的具体代码:

void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos);
	ListNode* prev = pos->prev;
	ListNode* newnode = ListNodeCreat(x);
	prev->next = newnode;
	newnode->prev = prev;
	newnode->next = pos;
	pos->prev = newnode;
}

这里是在pos位前面插入数据,实现起来也比较简单。

查删的具体代码:

void ListErase(ListNode* pos)
{
	assert(pos);
	ListNode* prev = pos->prev;
	ListNode* next = pos->next;
	prev->next = next;
	next->prev = prev;
	free(pos);
}

有了查删和查插后我们不难发现,头插和尾插都可以用查插实现,头删和尾删都可以用查删实现。

头插在 phead->next前插入,尾插在phead前插入,头删位置为phead->next,尾删位置为phead->prev.

在上面实现代码的时候注释掉的就是这种方法。


5 释放

void ListDestroy(ListNode* phead)
{
	ListNode* cur = phead;
	ListNode* next = phead->next;
	while (cur->next!=phead)
	{
		free(cur);
		cur = next;

		next = next->next;
	}
	
}

释放链表与单链表差不多,比较容易理解。

好了,今天的分享就到这里了,如果该文对你有帮助的话能不能3连支持一下博主呢?

d1feff5286c941c0bd431460f56c4563.gif

 

 

原网站

版权声明
本文为[努力上进呀]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_68872612/article/details/126187272