带头双链表的增删查改

 

带头双向链表是一种链表数据结构,相比于普通的双向链表,它包含一个额外的头结点。

带头双向链表的特点是:

  1. 头结点不存储实际数据,它仅用于标识链表的起点。
  2. 头结点的前驱指针(prev)指向链表的尾节点,头结点的后继指针(next)指向链表的第一个节点。
  3. 链表的最后一个节点的后继指针(next)指向头结点,链表的第一个节点的前驱指针(prev)也指向头结点,形成了循环。

带头双向链表的优点是:

  1. 头结点的存在简化了对链表的操作,可以方便地进行插入、删除等操作,而无需特殊处理链表为空的情况。
  2. 循环链表的结构可以更灵活地遍历链表中的所有节点,不需要额外的判断条件来结束遍历。

在实际应用中,带头双向链表常用于构建更复杂的数据结构,如双向循环队列、LRU Cache等。它也可以作为一种常见的链表实现方式,提供对链表的高效操作。

 


 头文件


#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
	LTDataType data;
	struct ListNode* next;
	struct ListNode* prev;
}ListNode;

// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
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);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);

创建返回链表的头结点


ListNode* ListCreate()
{
	ListNode* pHead = (ListNode*)malloc(sizeof(ListNode));
	if (pHead == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	pHead->data = 0;
	pHead->next = pHead;
	pHead->prev = pHead;
	
	return pHead;

}

 


双向链表销毁


void ListDestory(ListNode* pHead)
{
	if (pHead == NULL)
		return;

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

 


双向链表打印


void ListPrint(ListNode* pHead)
{
	assert(pHead);

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

 


 双向链表尾插


void ListPushBack(ListNode* pHead, LTDataType x)
{
	if (pHead == NULL)
		return;

	ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
	
	if (newNode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newNode->data = x;

	ListNode* cur = pHead->prev;
	newNode->next = pHead;
	newNode->prev = cur;
	pHead->prev = newNode;
	cur->next = newNode;
}

 


双向链表尾删


void ListPopBack(ListNode* pHead)
{
	if (pHead == NULL || pHead->next == pHead)
		return;

	ListNode* cur = pHead->prev;
	ListNode* prev = cur->prev;
	prev->next = pHead;
	pHead->prev = prev;
	free(cur);
}

 


双向链表头插


void ListPushFront(ListNode* pHead, LTDataType x)
{
	if (pHead == NULL)
		return;

	ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
	if (newNode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newNode->data = x;

	ListNode* first = pHead->next;
	newNode->next = first;
	newNode->prev = pHead;
	pHead->next = newNode;
	first->prev = newNode;

}

 


双向链表头删


void ListPopFront(ListNode* pHead)
{
	if (pHead == NULL || pHead->next == pHead)
		return;

	ListNode* first = pHead->next;
	ListNode* second = first->next;
	pHead -> next = second;
	second->prev = pHead;
	free(first);

}

 


双向链表查找


ListNode* ListFind(ListNode* pHead, LTDataType x)
{
	if (pHead == NULL)
		return NULL;

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

 


双向链表在pos的前面进行插入


void ListInsert(ListNode* pos, LTDataType x)
{
	if (pos == NULL)
		return;

	ListNode* prev = pos->prev;
	ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
	if (newNode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newNode->data = x;

	prev->next = newNode;
	newNode->prev = prev;
	newNode->next = pos;
	pos->prev = newNode;

}

 


双向链表删除pos位置的节点


void ListErase(ListNode* pos)
{
	if (pos == NULL || pos->next == pos)
		return;

	ListNode* prev = pos->prev;
	ListNode* next = pos->next;
	prev->next = next;
	next->prev = prev;
	free(pos);
}

 


测试


int main()
{
	ListNode* pHead = ListCreate();

	ListPushBack(pHead, 1);
	ListPushBack(pHead, 2);
	ListPushBack(pHead, 3);
	ListPrint(pHead);

	ListPopBack(pHead);
	ListPrint(pHead);

	ListPushFront(pHead, 4);
	ListPushFront(pHead, 5);
	ListPrint(pHead);

	ListPopFront(pHead);
	ListPrint(pHead);

	ListNode* foundNode = ListFind(pHead, 4);
	if (foundNode)
		printf("Found: %d\n", foundNode->data);

	ListInsert(foundNode, 5);
	ListPrint(pHead);

	ListErase(foundNode);
	ListPrint(pHead);

	ListDestory(pHead);

	return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值