数据结构-------双向链表的实现

双向链表的定义

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

图形表示如下:(该图形我们会在下面的代码解析中会用到)
在这里插入图片描述

双向链表的建立

因为双向链表有两个指针变量,我们定义前面的指针变量为 prev ;后面的指针变量为 next
建立双向链表,代码表示如下

typedef int LTDataType;
typedef struct ListNode
{
	struct ListNode* next;  //后指针
	struct ListNode* prev;  //前指针
	LTDataType data;
}LTNode;

双向链表的初始化

LTNode* BuyLTNode(LTDataType x) 函数是开辟空间函数,开辟一个名为node的链表元素的空间,将前后指针置空,将 x 赋值给date

代码实现如下:

LTNode* BuyLTNode(LTDataType x)
{
	LTNode* node = (LTNode*)malloc(sizeof(LTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	node->data = x;
	node->next = NULL;
	node->prev = NULL;
	return node;
}

到这里建立好的双向链表如下图所示:
在这里插入图片描述

代码实现如下:

LTNode* LTInit() 函数,初始化双向链表

LTNode* LTInit()
{
	LTNode* phead = BuyLTNode(-1);
	
	phead->next = phead;
    phead->prev = phead;

	return phead;
}

void LTPrint(LTNode* phead)函数,是一个简单的输出函数
就是遍历双向链表,创建cur 指针当cur == phaed 时循环结束
在遍历过程中以此对 data进行输出

代码实现如下:

void LTPrint(LTNode* phead)
{
	assert(phead);       //暴力检查phead是否为空

	printf("phead<=>");

	LTNode* cur = phead->next;
	while (cur != phead)    //遍历链表当cur == phead时循环结束
	{
		printf("%d<=>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

双向链表的查找

代码实现如下:

LTNode* LTFind(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

双向链表的尾插

图解如下:
在这里插入图片描述

就是说让
newhead 的头指针指向head
head 的尾指针指向 newnode

newnode 的尾指针指向 head
head 的头指针指向newnode
这样就实现了双向链表的尾插

代码实现如下:

void LTPushBack(LTNode* phead, LTDataType x)
{

	assert(phead);

	LTNode* tail = phead->prev;
	LTNode* newnode = BuyLTNode(x);

	newnode->prev = tail;
	tail->next = newnode;

	newnode->next = phead;
	phead->prev = newnode;

}

双向链表的尾删

图解如下
将tail与Ptail和head之间的连接阻断
然后连接head与Ptail
在这里插入图片描述

代码实现如下:

void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);

	LTNode* tail = phead->prev;
	LTNode* Ptail = tail->prev;
	free(tail);

	Ptail->next = phead;
	phead->prev = Ptail;

}

双向链表的头插

图解如下
在这里插入图片描述

void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* newnode = BuyLTNode(x);

	newnode->next = phead->next;
	phead->next->prev = newnode;

	phead->next = newnode;
	newnode->prev = phead;
}

双向链表的头删

图解如下:
在这里插入图片描述

void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);

	LTNode* first = phead->next;
	LTNode* second = first->next;
	free(first);

	phead->next = second;
	second->prev = phead;

	
}

统计双向链表中元素个数

int  LTSize(LTNode* phead)
{
	assert(phead);

	int size = 0;
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		++size;
		cur = cur->next;
	}
	return size;
}

在pos之前位置插入 x

图解如下:
在这里插入图片描述

//pos 之前插入 x
void LTInsert(LTNode* pos, LTDataType x)
{
	LTNode* newnode = BuyLTNode(x);
	LTNode* Ppos = pos->prev;

	Ppos->next = newnode;
	newnode->prev = Ppos;

	newnode->next = pos;
	pos->prev = newnode;

}

删除pos位置

图解如下:
在这里插入图片描述

//删除pos位置
void LTErase(LTNode* pos)
{
	assert(pos);

	LTNode* front = pos->prev;
	LTNode* behind = pos->next;

	free(pos);

	front->next = behind;
	behind->prev = front;


}

双向链表的释放

代码实现如下

void LTDestroy(LTNode* phead)
{
	assert(phead);

	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;

		free(cur);

		cur = next;
	}
	return NULL;
}

以上就是对双向链表的实现

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值