C语言带头结点的双向循环链表的实现

文章介绍了带头结点的双向循环链表在功能上的优势,如便于在任意位置插入和删除节点,以及一些操作的时间复杂度降低。文章提供了C语言实现的链表增删改查及销毁的代码示例,包括创建、打印、尾插、尾删、头插、头删、查找、插入和删除节点等操作。
摘要由CSDN通过智能技术生成

  在链表中,带头结点的双向循环链表是结构最复杂的链表,但是是功能最强大的链表,在使用更加方便的同时还能实现更多的功能。类似于以下的图片中的链表:

 

  相对于单链表,它的优点是可以在随机结点前插入结点,并且在增删改查中不仅操作简洁,而且有些操作的时间复杂度由O(n)直接降为O(1)。缺点是比单链表多一个头结点,需要额外开辟空间,并且每个结点要多一个prev指针来指向前一个结点,也就是多4个字节的空间来存放这个地址。

  但是总的来说,优远大于弊。虽然目前的刷题网站的链表题几乎都是以普通单链表为主,很少用到带头结点的双向循环链表,但是了解并熟练使用带头结点的双向循环链表对以后的要用到链表的时候还是很有用的。

  以下是用C语言来实现这个链表的增删改查及销毁,直接上代码!!!(先是头文件,然后是函数的实现)

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#define _CRT_SECURE_NO_WARNINGS//禁用所用警告
typedef int LTDataType;
typedef struct ListNode
{
	LTDataType data;
	ListNode* next;
	ListNode* prev;
}ListNode;
ListNode* BuyList(LTDataType x);//创建一个结点
void ListDestory(ListNode* pHead);//销毁链表
void ListPrint(ListNode* pHead);//打印链表
void ListPushBack(ListNode* pHead, LTDataType x);//尾插
void ListPopBack(ListNode* pHead);//尾删
void ListPushFront(ListNode* pHead, LTDataType x);//头插
void ListPopFront(ListNode* pHead);//头删
ListNode* ListFind(ListNode* pHead, LTDataType x);//查找
void ListInsert(ListNode* pos, LTDataType x);//在pos结点前插入
void ListErase(ListNode* pos);//删除pos位置

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

void ListDestory(ListNode* pHead)
{
	assert(pHead);
	ListNode* cur = pHead->next;
	while (cur != pHead)
	{
		ListNode* tmp = cur->next;
		free(cur);
		cur = tmp;
	}
	free(pHead);
}

void ListPrint(ListNode* pHead)
{
	assert(pHead);
	ListNode* cur = pHead->next;
	while (cur!=pHead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

void ListPushBack(ListNode* pHead, LTDataType x)
{
	assert(pHead);
	ListNode* newnode = BuyList(x);
	newnode->prev = pHead->prev;
	newnode->next = pHead;
	pHead->prev->next = newnode;
	pHead->prev = newnode;
}

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

void ListPushFront(ListNode* pHead, LTDataType x)
{
	assert(pHead);
	ListNode* frist = BuyList(x);
	ListNode* second = pHead->next;
	frist->next = second;
	frist->prev = pHead;
	pHead->next = frist;
	second->prev = frist;
}

void ListPopFront(ListNode* pHead)
{
	assert(pHead);
	assert(pHead->next);
	ListNode* next = pHead->next;
	ListNode* second = next->next;
	pHead->next = second;
	second->prev = next->prev;
	free(next);
}

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

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

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

  希望对你有帮助!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值