带头带环双向链表的实现及其相关操作。。

    在前面博客中我们讲到关于线性表中的单链表,我们实现了不带头不带环的单项链表,

在链表中不带头不带环的单链表是相对比其他链表要麻烦,且应用相对较少。那么今天

我们来实现带头带环的双向链表,带头带环双向链表相应用比较多,应为它比较简介,相关的操作

相对简单。

    那么我们来看一下声明:

#pragma once

#include<stdio.h>
#include<stdlib.h>

#define FUNCTIONNAME printf("\n================%s=============\n",__FUNCTION__)

typedef char LinkType;

typedef struct DLinkNode{
	LinkType data;
	struct DLinkNode *prev;
	struct DLinkNode *next;
}DLinkNode;

// 初始化链表。
void DLinkNodeInit(DLinkNode *head);

// 尾插一个元素。
void DLninkNodePushBack(DLinkNode *head, LinkType value);

// 尾删一个元素。
void DLinkNodePopBack(DLinkNode *head);

// 头插入一个元素。
void DLinkNodePushFront(DLinkNode *head, LinkType value);

// 头删一个元素。
void DLinkNodePopFront(DLinkNode *head);

// 查找指定元素。
DLinkNode* DLinkNodeFind(DLinkNode *head, LinkType find);

// 在指定位置之前插入一个元素。
void DLinkNodeInsertFront(DLinkNode *pos, LinkType value);

// 在指定元素之后插入一个元素。
void DLinkNodeInsertBack(DLinkNode *pos, LinkType value);

// 删除指定位置的节点。
void DLinkNodeErase(DLinkNode *head,DLinkNode *pos);

// 删除指定元素的第一个节点。
void DLinkNodeRemove(DLinkNode *head, LinkType value);

// 删除指定元素的所有节点。
void DLinkNodeRemoveAll(DLinkNode *head, LinkType value);

// 求链表的长度
size_t DLinkNodeSize(DLinkNode *head);

// 判读链表是否为空。
int DLinkNodeEmpty(DLinkNode *head);

声明的相关函数实现:

相关单元测试:

#include "DLinkNode.h"

void DLinkNodePrint(DLinkNode *head)
{
	if (head == NULL)
	{
		return;
	}
	DLinkNode *cur = head->next;
	printf("head->");
	for (;cur != head;cur = cur->next)
	{
		printf("[%c %p]->",cur->data,cur);
	}
	printf("head\n");
}

// 初始化链表。
void DLinkNodeInit(DLinkNode *head)
{
	if (head == NULL)
	{
		// 非法输入
		return;
	}
	head->next = head;
	head->prev = head;
}

// 创建节点
DLinkNode *CreatNode(LinkType value)
{
	DLinkNode *node = (DLinkNode*)malloc(sizeof(DLinkNode));
	if (node == NULL)
	{
		// 开辟空间失败。
		return;
	}
	node->data = value;
	node->next = NULL;
	node->prev = NULL;
	return node;
}

// 尾插一个元素。
DLinkNode *DLinkNodePushBack(DLinkNode *head, LinkType value)
{
	if (head == NULL)
	{
		// 非法输入。
		return NULL;
	}
	DLinkNode *new_node = CreatNode(value);
	DLinkNode *pre = head->prev;
	pre->next = new_node;
	new_node->prev = pre;

	new_node->next = head;
	head->prev = new_node;
	return new_node;
}

// 尾删一个元素。
void DLinkNodePopBack(DLinkNode *head)
{
	if (head == NULL)
{
		// 非法输入。
		return;
	}
	if (head->next == head)
	{
		// 空链表。
		return;
	}
	DLinkNode *delete = head->prev;
	DLinkNode *pre = delete->prev;
	pre->next = head;
	head->prev = pre;
	free(delete);
}

// 头插入一个元素。
void DLinkNodePushFront(DLinkNode *head, LinkType value)
{
	if (head == NULL)
	{
		return;
	}
	DLinkNode *new_node = CreatNode(value);
	DLinkNode *next = head->next;
	head->next = new_node;
	new_node->prev = head;
	
	next->prev = new_node;
	new_node->next = next;
}

// 头删一个元素。
void DLinkNodePopFront(DLinkNode *head)
{
	if (head == NULL)
	{
		// 非法输入。
		return;
	}
	if (head->next == head)
	{
		// 链表为空。
		return;
	}
	DLinkNode *delete = head->next;
	DLinkNode *next = delete->next;
	head->next = next;
	next->prev = head;
	free(delete);
}

// 查找指定元素。
DLinkNode* DLinkNodeFind(DLinkNode *head, LinkType find)
{
	if (head == NULL || head->next == head)
	{
		// 链表为空或者非法输入。
		return NULL;
	}
	DLinkNode *cur = head->next;
	while (cur != head)
	{
		if (cur->data == find)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

// 在指定位置之前插入一个元素。
void DLinkNodeInsertFront(DLinkNode *pos, LinkType value)
{
	if (pos == NULL)
	{
		// 非法输入。
		return;
	}
	DLinkNode *new_node = CreatNode(value);
	DLinkNode *prev = pos->prev;
	prev->next = new_node;
	new_node->prev = prev;

	new_node->next = pos;
	pos->prev = new_node;
}


// 在指定元素之后插入一个元素。
void DLinkNodeInsertBack(DLinkNode *pos, LinkType value)
{
	if (pos == NULL)
	{
		// 非法输入。
		return;
	}
	DLinkNode *new_node = CreatNode(value);
	DLinkNode *next = pos->next;
	pos->next = new_node;
	new_node->prev = pos;

	new_node->next = next;
	next->prev = new_node;
}

// 删除指定位置的节点。
void DLinkNodeErase(DLinkNode *head,DLinkNode *pos)
{
	if (pos == NULL)
	{
		// 非法输入。
		return;
	}
	DLinkNode *cur = head->next;
	while (cur != head)
	{
		if (cur == pos)
		{
			DLinkNode *prev = pos->prev;
			DLinkNode *next = pos->next;
			prev->next = next;
			next->prev = prev;
			free(pos);
			return;
		}
		cur = cur->next;
	}
	printf("pos位置有误\n");
	return;
}


// 删除指定元素的第一个节点。
void DLinkNodeRemove(DLinkNode *head, LinkType value)
{
	if (head  == NULL)
	{
		// 非法输入。
		return;
	}
	DLinkNode *cur = head->next;
	while (cur != head)
	{
		if (cur->data == value)
		{
			DLinkNode *prev = cur->prev;
			DLinkNode *next = cur->next;
			prev->next = next;
			next->prev = prev;
		}
		cur = cur->next;
	}
}

// 删除指定元素的所有节点。
void DLinkNodeRemoveAll(DLinkNode *head, LinkType value)
{
	if (head == NULL)
	{
		return;
	}
	DLinkNode *pos;// = DLinkNodeFind(head,value);
	while (pos != NULL)
	{
		pos = DLinkNodeFind(head,value);
		DLinkNodeErase(head,pos);
	}
	return;
}


// 求链表的长度
size_t DLinkNodeSize(DLinkNode *head)
{
	if (head == NULL)
	{
		return (size_t)-1;
	}
	DLinkNode *cur = head->next;
	size_t count = 0;
	while (cur != head)
	{
		++count;
		cur = cur->next;
	}
	return count;
}

// 判读链表是否为空。
int DLinkNodeEmpty(DLinkNode *head)
{
	if (head == NULL)
	{
		return (size_t)-1;
	}
	if (head->next = head)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

///
//以下是测试代码
///

// 初始化。
void TestDLinkNodeInit()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
}

// 尾插。
void TestDLinkNodePushBack()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNodePushBack(&head,'a');
	DLinkNodePushBack(&head,'b');
	DLinkNodePushBack(&head,'c');
	DLinkNodePushBack(&head,'d');
	DLinkNodePrint(&head);
}

// 尾删。
void TestDLinkNodePopBack()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNodePushBack(&head,'a');
	DLinkNodePushBack(&head,'b');
	DLinkNodePushBack(&head,'c');
	DLinkNodePushBack(&head,'d');
	DLinkNodePrint(&head);
	DLinkNodePopBack(&head);
	DLinkNodePopBack(&head);
	DLinkNodePopBack(&head);
	DLinkNodePrint(&head);
	DLinkNodePopBack(&head);
	DLinkNodePopBack(&head);
	DLinkNodePrint(&head);
}

// 头插。
void TestDLinknodePushFront()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNodePushFront(&head,'a');
	DLinkNodePushFront(&head,'b');
	DLinkNodePrint(&head);
	DLinkNodePushFront(&head,'d');
	DLinkNodePrint(&head);
}

// 头删。
void TestDLinkNodePopFront()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNodePushFront(&head,'a');
	DLinkNodePushFront(&head,'b');
	DLinkNodePushFront(&head,'d');
	DLinkNodePrint(&head);
	DLinkNodePopFront(&head);
	DLinkNodePrint(&head);
	DLinkNodePopFront(&head);
	DLinkNodePopFront(&head);
	DLinkNodePrint(&head);
	DLinkNodePopFront(&head);
	DLinkNodePrint(&head);
}

// 按元素查找的位置。
void TestDLinkNodeFind()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNodePushFront(&head,'a');
	DLinkNode *pos = DLinkNodePushBack(&head,'b');
	DLinkNodePushFront(&head,'c');
	DLinkNodePushFront(&head,'d');
	DLinkNodePushFront(&head,'e');
	DLinkNodePrint(&head);
	DLinkNode *ret = DLinkNodeFind(&head, 'b');
	printf("except %p actual %p \n",pos, ret);
}

// 指定位置之前插入一个元素。
void TestDLinkNodeInsertFront()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNode *pos1 = DLinkNodePushBack(&head,'a');
	DLinkNode *pos = DLinkNodePushBack(&head,'b');
	DLinkNodePushBack(&head,'c');
	DLinkNodePushBack(&head,'d');
	DLinkNodePushBack(&head,'e');
	DLinkNodePrint(&head);
	DLinkNodeInsertFront(pos,'f');
	DLinkNodePrint(&head);
	DLinkNodeInsertFront(pos1,'g');
	DLinkNodePrint(&head);
}

// 指定位置之后插入一个元素。
void TestDLinkNodeInsertBack()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNode *pos1 = DLinkNodePushBack(&head,'a');
	DLinkNodePushBack(&head,'b');
	DLinkNodePushBack(&head,'c');
	DLinkNodePushBack(&head,'d');
	DLinkNode *pos = DLinkNodePushBack(&head,'e');
	DLinkNodePrint(&head);
	DLinkNodeInsertBack(pos1,'f');
	DLinkNodeInsertBack(pos,'g');
	DLinkNodePrint(&head);
}

// 删除指定位置节点。
void TestDLinkNodeErase()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNode *pos1 = DLinkNodePushBack(&head,'a');
	DLinkNodePushBack(&head,'b');
	DLinkNodePushBack(&head,'c');
	DLinkNodePushBack(&head,'d');
	DLinkNode *pos = DLinkNodePushBack(&head,'e');
	DLinkNodePrint(&head);
	DLinkNodeErase(&head,pos1);
	DLinkNodePrint(&head);
	DLinkNodeErase(&head,pos);
	DLinkNodePrint(&head);
}

// 删除指定元素的第一个节点。
void TestDLinkNodeRemove()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNode *pos1 = DLinkNodePushBack(&head,'a');
	DLinkNodePushBack(&head,'b');
	DLinkNodePushBack(&head,'c');
	DLinkNodePushBack(&head,'d');
	DLinkNode *pos = DLinkNodePushBack(&head,'e');
	DLinkNodePrint(&head);
	DLinkNodeRemove(&head,'b');
	DLinkNodePrint(&head);
	DLinkNodeRemove(&head,'a');
	DLinkNodePrint(&head);
}

// 删除指定元素的所有节点。
void TestDLinkNodeRemoveAll()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	DLinkNode *pos1 = DLinkNodePushBack(&head,'a');
	DLinkNodePushBack(&head,'b');
	DLinkNodePushBack(&head,'c');
	DLinkNodePushBack(&head,'d');
	DLinkNode *pos = DLinkNodePushBack(&head,'c');
	DLinkNodePrint(&head);
	DLinkNodeRemoveAll(&head,'a');
	DLinkNodePrint(&head);
	DLinkNodeRemoveAll(&head,'c');
	DLinkNodePrint(&head);
}

// 判断链表是否为空,不为空求出链表的长度。
void TestDLinkNodeSize()
{
	FUNCTIONNAME;
	DLinkNode head;
	DLinkNodeInit(&head);
	int ret = DLinkNodeEmpty(&head);
	DLinkNode *pos1 = DLinkNodePushBack(&head,'a');
	DLinkNodePushBack(&head,'b');
	DLinkNodePushBack(&head,'c');
	DLinkNodePushBack(&head,'d');
	DLinkNode *pos = DLinkNodePushBack(&head,'c');
	DLinkNodePrint(&head);
	size_t size = DLinkNodeSize(&head);
	printf("except 1 actual %d\n",ret);
	printf("except 5 actual %d\n",size);
}

int main()
{
	TestDLinkNodeInit();
	TestDLinkNodePushBack();
	TestDLinkNodePopBack();
	TestDLinknodePushFront();
	TestDLinkNodePopFront();
	TestDLinkNodeFind();
	TestDLinkNodeInsertFront();
	TestDLinkNodeInsertBack();
	TestDLinkNodeErase();
	TestDLinkNodeRemove();
	TestDLinkNodeRemoveAll();
	TestDLinkNodeSize();
	return 0;
}

如有问题请多多指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值