数据结构之双向链表和双向循环链表

一:双向链表

(一):双向链表的结构

双向链表是链表的一种,它的每个节点中都有两个指针:前指针和后指针。分别指向节点的前驱和后继。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
其结构如下示意图所示:
链表中任意两相邻的节点通过前后指针相互相连。
在这里插入图片描述
节点:
在这里插入图片描述

(二):数据的构建

节点:节点是描述结构体的基本单元,抽象单一个体
节点:

struct Node
{
	int data;
	struct Node* front;//前指针		或称左指针(left)
	struct Node* tail;//后指针		或称右指针(right)
};

链表的封装:描述结构的特征
链表:

struct List
{
	//万金油参数
	int size;
	struct Node* firstNode;//首节点
	struct Node* lastNode;//尾节点
};

(三):创建节点

//1.创建节点
struct Node* createNode(int data)
{
	struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));//为节点申请内存
	//节点的初始化
	newNode->data = data;
	newNode->front = NULL;
	newNode->tail = NULL;
	return newNode;
}

(四):创建链表

//2.创建链表
struct List* createList()
{
	struct List* list = (struct List*)malloc(sizeof(struct List));//为链表申请内存
	//初始化变量
	list->size = 0;
	list->firstNode = NULL;
	list->lastNode = NULL;
	return list;
}

(五):插入

1:表头法插入

注意:
1.当链表为空时,进行插入链表的首节点和尾节点都指向新插入的节点
2.不为空时,进行插入要做好"连线",即连接插入节点和首节点,然后注意让list->firstNode始终指向首节点即:list->firstNode=newNode

//3.表头法插入
void insertNodeByHead(struct List* list, int data)//函数参数的确定:插入到哪个链表,插入的数据是什么
{
	struct Node* newNode = createNode(data);//创建插入的节点
	if (list->size==0)
	{
		list->firstNode = newNode;//当链表为空时进行插入,list链表的first和last全都指向新节点newNode
		list->lastNode = newNode;
	}
	else
	{
		//这里进行节点之间的连接需要连接两条线并且移动list->firstNode,使其始终指向首节点
		list->firstNode->front = newNode;//做连接
		newNode->tail = list->firstNode;//做连接
		list->firstNode = newNode; //将list->firstNode一直指向首节点
	}
	list->size++;
}

2:表尾法插入

表尾法插入的过程
1.当链表为空时,首节点和尾节点指向newNode
2.链表不为空时,做连接,连接尾节点和新插入的节点
3.不要忘记将list->last始终指向尾节点

//4.表尾插入
void insertNodeByTail(struct List* list, int data)//函数参数的确定:插入到哪个链表,插入的数据是什么
{
	struct Node* newNode = createNode(data);//创建插入的节点
	if (list->size == 0)
	{
		list->firstNode = newNode;
		list->lastNode = newNode;
	}
	else
	{
		//与表头法插入类似,连接两条线,然后移动list->lastNode使其一直指向尾节点
		list->lastNode->tail = newNode;
		newNode->front = list->lastNode;
		list->lastNode = newNode;
	}
	list->size++;
}

3:指定位置插入

指定位置插入(指定位置删除)等首要任务都是找到指定的位置,然后将插入的数据节点与指定位置前节点,指定位置后节点做连接即可我们需要找到指定位置节点以及指定位置前的节点,因此的我们需要两个相邻的移动节点posNode和posFrontNode
过程:
1:首先判断是否首节点为指定位置节点,若是则头插法
2:当首节点不是指定位置节点时,通过两个并排的移动指针往后找
3:跳出循环后,posNode指向NULL则链表中无指定位置节点,无法进行插入
4:posNode不指向NULL时,则指向指定位置节点,此时在posNode和posFrontNode之间做连线即可
注意:需要连接四条线

//5.指定位置插入
void insertNodeByAppoin(struct List* list, int posData, int data)//参数的确定:要插入到哪个链表(list),插到哪个数据的前面(posData),要插入的数据(data)
{

	struct Node* posFrontNode = list->firstNode;
	struct Node* posNode = list->firstNode->tail;
	if (posFrontNode->data==posData)//当首节点为指定位置节点时,进行头插法
	{
		insertNodeByHead(list, data);
	}
	else
	{
		while (posNode->data != posData)//一直等到找到指定位置或者找到结尾然后跳出
		{
			posFrontNode = posNode;//节点并排往后移动
			posNode = posNode->tail;
			if (posNode == NULL)//走到最后面退出来
			{
				break;
			}
		}
		if (posNode == NULL)//判断posNode的转态是指向指定位置节点还是指向NULL(未找到数据)
		{
			printf("未找到指定数据,无法插入。\n");
		}
		else
		{
			struct Node* newNode = createNode(data);///创建节点
			newNode->tail = posNode;//然后进行做连接,newNode与posNode,posFrontNode分别做连接,将newNode放到posNode和posFrontNode的中间。需要连接4条线
			posNode->front = newNode;
			newNode->front = posFrontNode;
			posFrontNode->tail = newNode;
		}
		list->size++;
	}
}

(六):删除

1:头删除

//6.头删
void deleteNodeByHead(struct List* list)//要删除哪个节点
{
	if (list->size == 0)//当链表为空时,无法删除
	{
		printf("链表为空,无法进行删除\n");
	}
	else
	{
		struct Node* nextNode = list->firstNode->tail;//保存一下链表list的第二个节点
		free(list->firstNode);
		list->firstNode = nextNode;//list->firstNode始终指向链表的首节点
		list->size--;
	}
}

2:尾删

注意:list->lastNode指向previousNode后,previousNode的后指针不为NULL,这时需要将list->lastNode的后指针指向NULL

//7.尾删
void deleteNodeByTail(struct List* list)
{
	if (list->size == 0)//当链表为空时,无法删除
	{
		printf("链表为空,无法进行删除\n");
	}
	else
	{
		struct Node* previousNode = list->lastNode->front;//保存一下链表list的倒数第二个指针
		free(list->lastNode);
		list->lastNode = previousNode;//list->lastNode始终指向链表的尾节点
		list->lastNode->tail = NULL;  //注意这一点不能遗漏,
		//再次犯错!!!,previousNode=list->lastNode->front的tail不止向NULL
		//因此,这里list->lastNode=previousNode后,需要将list->lastNode的后指针指向NULL
		list->size--;
	}
}

3:指定位置删除

//8.指定位置删除
void deleteNodeByAppoin(struct List* list, int posData)
{
	struct Node* posFrontNode = list->firstNode;
	struct Node* posNode = list->firstNode->tail;
	if (posFrontNode->data==posData)
	{
		deleteNodeByHead(list);
	}
	else
	{
		while (posNode->data != posData)
		{
			posFrontNode = posNode;
			posNode = posNode->tail;
			if (posNode == NULL)
			{
				break;
			}
		}
		if (posNode == NULL)
		{
			printf("未找到指定位置,无法删除\n");
		}
		else
		{
			posFrontNode->tail = posNode->tail;//做连线,将posFrontNode和posNode->tail连接到一起
			posNode->tail->front = posFrontNode;
			free(posNode);//清理posNode
			posNode = NULL;//置空
			list->size--;
		}
	}
}

(七):链表的打印

这里的每一个节点都有前指针和后指针。很容易通过后指针进行顺序打印,通过前指针进行逆序打印。

//9.顺序打印(通过后指针)
void printListByTail(struct List* list)//通过节点的后指针进行顺序打印
{
	if (list->size == 0)
	{
		printf("链表为空,无法打印\n");
	}
	else
	{
		struct Node* pMove = list->firstNode;
		printf("顺序打印:");
		while (pMove)
		{
			printf("%d ", pMove->data);
			pMove = pMove->tail;
		}
		printf("\n");
	}
}
//10.逆序打印(通过前指针)
void printListByFront(struct List* list)//通过节点的前指针进行顺序打印
{
	if (list->size == 0)
	{
		printf("链表为空,无法打印\n");
	}
	else
	{
		struct Node* pMove = list->lastNode;
		printf("逆序打印:");
		while (pMove)
		{
			printf("%d ", pMove->data);
			pMove = pMove->front;
		}
		printf("\n");
	}
}

(八):完整测试代码

//双向循环链表 约瑟环问题  杀人游戏
#include<stdio.h>
#include<stdlib.h>
struct Node
{
	int data;
	struct Node* front;
	struct Node* tail;
};
//创建节点
struct Node* createNode(int data)
{
	struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
	newNode->data = data;
	newNode->front = NULL;
	newNode->tail = NULL;
	return newNode;
}
//创建链表
struct Node* createList()//headNode里不存放数据
{
	struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
	headNode->front = headNode;
	headNode->tail = headNode;
	return headNode;
}
//头插
void insertNodeByFront(struct Node* headNode, int data)
{
	struct Node* newNode = createNode(data);
	struct Node* nextNode = headNode->tail;//记录一下首节点的下一位
	//做连线  四条线
	headNode->tail = newNode;//首节点的后指针指向新节点
	newNode->front = headNode;//新节点的前指针指向首节点
	newNode->tail = nextNode;//新节点的后指针指向首节点的下一位
	nextNode->front = newNode;//首节点的下一位前指针指向新节点
}
//尾插
void insertNodeByTail(struct Node* headNode, int data)
{
	struct Node* newNode = createNode(data);
	struct Node* tailNode = headNode->front;//首节点的前指针的指向尾节点
	//连接四根线
	tailNode->tail = newNode;//尾节点的后指针指向新节点
	newNode->front = tailNode;//新节点的前指针指向尾节点
	headNode->front = newNode;//首节点的前指针指向新节点
	newNode->tail = headNode;//新节点的后指针指向头节点
}
//指定位置插入
void insertNodeByAppoin(struct Node* headNode, int posData, int data)
{
	if (headNode->front == headNode && headNode->tail == headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("链表为NULL,无法插入\n");
	}
	else
	{
		struct Node* posFrontNode = headNode;
		struct Node* posNode = headNode->tail;
		while (posNode->data != posData)
		{
			posFrontNode = posNode;
			posNode = posNode->tail;
			while (posNode == headNode)
			{
				break;
			}
		}
		if (posNode == headNode)
		{
			printf("未找到指定位置,无法做指定位置插入\n");
		}
		else
		{
			struct Node* newNode = createNode(data);//创建节点
			//做连线,四条连线
			posFrontNode->tail = newNode;//指定位置前节点的后指针指向新节点
			newNode->front = posFrontNode;//新节点的前指针指向指定位置节点
			posNode->front = newNode;//指定位置节点的前指针指向新节点
			newNode->tail = posNode;//新节点的后指针指向指定位置节点
		}
	}
}
//删除
//头删除
void deleteNodeByHead(struct Node* headNode)
{
	if (headNode->front == headNode&&headNode->tail==headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("链表为NULL,无法进行删除\n");
	}
	else
	{
		struct Node* nextNode = headNode->tail;//记录一下第一个数据节点
		//做连接:头节点的尾指针指向nextNode的tail
		headNode->tail = nextNode->tail;
		//nextNode->tail的头指针指向headNode
		nextNode->tail->front = headNode;
		//清理第一个数据节点
		free(nextNode);
		nextNode = NULL;
	}
}
//尾删除
void deleteNodeByTail(struct Node* headNode)
{
	if (headNode->front == headNode && headNode->tail == headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("链表为NULL,无法进行删除。\n");
	}
	else
	{
		struct Node* tailNode = headNode->front;//找到尾节点,headNode的前指针就是尾节点
		tailNode->front->tail = headNode;
		headNode->front = tailNode->front;
		free(tailNode);
		tailNode = NULL;
	}
}
//指定位置删除
void deleteNodeByAppoin(struct Node* headNode, int posData)
{
	struct Node* posFrontNode = headNode;
	struct Node* posNode = headNode->tail;
	if (posNode->data == posData)//首个数据节点的数据等于指定数据时,头删除
	{
		deleteNodeByHead(headNode);
	}
	else
	{
		while (posNode->data != posData)
		{
			posFrontNode = posNode;
			posNode = posNode->tail;
			if (posNode == headNode)//循环一圈回到headNode,说明没有指定数据。退出
			{
				break;
			}
		}
		if (posNode == headNode)//判断posNode的状态
		{
			printf("没有找到指定数据,无法进行删除。\n");
		}
		else
		{
			posFrontNode->tail = posNode->tail;
			posNode->tail->front = posFrontNode;
			free(posNode);
			posNode = NULL;
		}
	}
}

//打印测试
//通过后指针打印遍历
void printListByTail(struct Node* headNode)
{
	if (headNode->front == headNode&&headNode->tail==headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("表为NULL,无法打印\n");
		return;
	}
	struct Node* pMove = headNode->tail;
	printf("通过后指针打印\n");
	while (pMove != headNode)
	{
		printf("%d ", pMove->data);
		pMove = pMove->tail;
	}
	printf("\n"); 
}
//通过前指针打印遍历
void printListByFront(struct Node* headNode)
{
	if (headNode->front == headNode&&headNode->tail==headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("表为NULL,无法打印\n");
		return;
	}
	struct Node* pMove = headNode->front;
	printf("通过后指针打印\n");
	while (pMove != headNode)
	{
		printf("%d ", pMove->data);
		pMove = pMove->front;
	}
	printf("\n");
}
int main()
{
	//创建链表
	struct Node* list = createList();
	
	//尾插法
	insertNodeByTail(list, 3);
	insertNodeByTail(list, 2);
	insertNodeByTail(list, 1);
	printListByTail(list);
	printListByFront(list);
	printListByTail(list);

	//头插法
	insertNodeByFront(list, 4);
	insertNodeByFront(list, 5);
	insertNodeByFront(list, 6);
	printListByTail(list);

	//指定位置插入
	insertNodeByAppoin(list, 6, 7);
	printListByTail(list);

	//头删
	deleteNodeByHead(list);
	deleteNodeByHead(list);
	printListByTail(list);

	//尾删
	deleteNodeByTail(list);
	deleteNodeByTail(list);
	printListByTail(list);

	//指定位置删除
	deleteNodeByAppoin(list, 4);
	deleteNodeByAppoin(list, 3);
	deleteNodeByAppoin(list, 5);
	printListByTail(list);
	return 0;
}

二:双向循环链表

(一):双向循环链表的结构

双向循环链表的结构如下:
它是在双向链表的基础上,将双向链表的首节点指向尾节点,尾节点指向首节点。使得各个节点之间通过指针连接成环。

在这里插入图片描述
连接成环后,这里就没有严格上的首节点和尾节点了,也没有严格上的“前”和“后”节点了。为了实现以及描述的方便:我们在双向循环链表中取一个节点作为标记headNode(我们这里headNode中不存放数据相当于表头),其headNode的前指针指向tailNode。这样我们就可以,用双向链表的操作来操作这个结构了。

当然,这里我们也可以使用再封装的方式,或者headNode中也存放数据。写法会略微有点不同,可以尝试着自己去实现。

变形如下:
在这里插入图片描述
节点(结构体)的结构:-
与循环链表的中节点的结构相同

在这里插入图片描述

(二):数据的构建

1:节点:

struct Node
{
	int data;              //数据域
	struct Node* front;    //前指针
	struct Node* tail;     //后指针
};

2:创建节点:

//创建节点
struct Node* createNode(int data)
{
	struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));//为节点申请内存
	//初始化数据
	newNode->data = data;
	newNode->front = NULL;
	newNode->tail = NULL;
	return newNode;
}

3:创建链表:
初始状态:headNode的前后指针都指向本身。

//创建链表
struct Node* createList()//headNode里不存放数据
{
	struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));//为节点申请内存
	//初始状态headNode的前指针指向headNode(本身),headNode的后指针指向headNode(本身)
	headNode->front = headNode;
	headNode->tail = headNode;
	return headNode;
}

图示:
在这里插入图片描述

(三):插入

1:头插

做好连线即可……

//1.头插
void insertNodeByFront(struct Node* headNode, int data)
{
	struct Node* newNode = createNode(data);
	struct Node* nextNode = headNode->tail;//记录一下首节点的下一位
	//做连线  四条线
	headNode->tail = newNode;//首节点的后指针指向新节点
	newNode->front = headNode;//新节点的前指针指向首节点
	
	newNode->tail = nextNode;//新节点的后指针指向首节点的下一位
	nextNode->front = newNode;//首节点的下一位前指针指向新节点
}

2:尾插

做好连线即可……
但是注意一点:这里的循环链表中headNode->front即为尾节点

//2.尾插
void insertNodeByTail(struct Node* headNode, int data)
{
	struct Node* newNode = createNode(data);
	struct Node* tailNode = headNode->front;//首节点的前指针的指向尾节点
	//连接四根线
	tailNode->tail = newNode;//尾节点的后指针指向新节点
	newNode->front = tailNode;//新节点的前指针指向尾节点
	
	headNode->front = newNode;//首节点的前指针指向新节点
	newNode->tail = headNode;//新节点的后指针指向头节点
}

3:指定位置插入

当headNode的前后指针都指向headNode(本身)时。链表为空

错点:刚开始写时,我以为headNode的前后指针的指向一样时即可判断为空,但是后来打印时有错误,即链表中有一个数据节点时会有错误。因为链表中有一个数据节点时,headNode的前后指针都指向该数据节点。故headNode->front==headNode->tail并不是判断其为空的条件

//指定位置插入
void insertNodeByAppoin(struct Node* headNode, int posData, int data)
{
	if (headNode->front == headNode && headNode->tail == headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("链表为NULL,无法插入\n");
	}
	else
	{
		struct Node* posFrontNode = headNode;
		struct Node* posNode = headNode->tail;
		while (posNode->data != posData)
		{
			posFrontNode = posNode;
			posNode = posNode->tail;
			while (posNode == headNode)
			{
				break;
			}
		}
		if (posNode == headNode)
		{
			printf("未找到指定位置,无法做指定位置插入\n");
		}
		else
		{
			struct Node* newNode = createNode(data);//创建节点
			//做连线,四条连线
			posFrontNode->tail = newNode;//指定位置前节点的后指针指向新节点
			newNode->front = posFrontNode;//新节点的前指针指向指定位置节点
			posNode->front = newNode;//指定位置节点的前指针指向新节点
			newNode->tail = posNode;//新节点的后指针指向指定位置节点
		}
	}
}

(四):删除

1:头删

//4.头删除
void deleteNodeByHead(struct Node* headNode)
{
	if (headNode->front == headNode&&headNode->tail==headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("链表为NULL,无法进行删除\n");
	}
	else
	{
		struct Node* nextNode = headNode->tail;//记录一下第一个数据节点
		//做连接:头节点的尾指针指向nextNode的tail
		headNode->tail = nextNode->tail;
		//nextNode->tail的头指针指向headNode
		nextNode->tail->front = headNode;
		//清理第一个数据节点
		free(nextNode);
		nextNode = NULL;
	}
}

2:尾删

//5.尾删除
void deleteNodeByTail(struct Node* headNode)
{
	if (headNode->front == headNode && headNode->tail == headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("链表为NULL,无法进行删除。\n");
	}
	else
	{
		struct Node* tailNode = headNode->front;//找到尾节点,headNode的前指针就是尾节点
		tailNode->front->tail = headNode;
		headNode->front = tailNode->front;
		free(tailNode);
		tailNode = NULL;
	}
}

3:指定位置删除

注意:posNode比对一圈后回到headNode则说明没有找到指定数据。

//6.指定位置删除
void deleteNodeByAppoin(struct Node* headNode, int posData)
{
	struct Node* posFrontNode = headNode;
	struct Node* posNode = headNode->tail;
	if (posNode->data == posData)//首个数据节点的数据等于指定数据时,头删除
	{
		deleteNodeByHead(headNode);
	}
	else
	{
		while (posNode->data != posData)
		{
			posFrontNode = posNode;
			posNode = posNode->tail;
			if (posNode == headNode)//循环一圈回到headNode,说明没有指定数据。退出
			{
				break;
			}
		}
		if (posNode == headNode)//判断posNode的状态
		{
			printf("没有找到指定数据,无法进行删除。\n");
		}
		else
		{
			posFrontNode->tail = posNode->tail;
			posNode->tail->front = posFrontNode;
			free(posNode);
			posNode = NULL;
		}
	}
}

(五):打印

有前后指针,使得顺序逆序遍历很方便

//打印测试
//通过后指针打印遍历
void printListByTail(struct Node* headNode)
{
	if (headNode->front == headNode&&headNode->tail==headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("表为NULL,无法打印\n");
		return;
	}
	struct Node* pMove = headNode->tail;
	printf("通过后指针打印\n");
	while (pMove != headNode)
	{
		printf("%d ", pMove->data);
		pMove = pMove->tail;
	}
	printf("\n"); 
}
//通过前指针打印遍历
void printListByFront(struct Node* headNode)
{
	if (headNode->front == headNode&&headNode->tail==headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("表为NULL,无法打印\n");
		return;
	}
	struct Node* pMove = headNode->front;
	printf("通过后指针打印\n");
	while (pMove != headNode)
	{
		printf("%d ", pMove->data);
		pMove = pMove->front;
	}
	printf("\n");
}

(六):完整测试代码

//双向循环链表
#include<stdio.h>
#include<stdlib.h>
struct Node
{
	int data;
	struct Node* front;
	struct Node* tail;
};
//创建节点
struct Node* createNode(int data)
{
	struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
	newNode->data = data;
	newNode->front = NULL;
	newNode->tail = NULL;
	return newNode;
}
//创建链表
struct Node* createList()//headNode里不存放数据
{
	struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
	headNode->front = headNode;
	headNode->tail = headNode;
	return headNode;
}
//1.头插
void insertNodeByFront(struct Node* headNode, int data)
{
	struct Node* newNode = createNode(data);
	struct Node* nextNode = headNode->tail;//记录一下首节点的下一位
	//做连线  四条线
	headNode->tail = newNode;//首节点的后指针指向新节点
	newNode->front = headNode;//新节点的前指针指向首节点
	newNode->tail = nextNode;//新节点的后指针指向首节点的下一位
	nextNode->front = newNode;//首节点的下一位前指针指向新节点
}
//2.尾插
void insertNodeByTail(struct Node* headNode, int data)
{
	struct Node* newNode = createNode(data);
	struct Node* tailNode = headNode->front;//首节点的前指针的指向尾节点
	//连接四根线
	tailNode->tail = newNode;//尾节点的后指针指向新节点
	newNode->front = tailNode;//新节点的前指针指向尾节点
	headNode->front = newNode;//首节点的前指针指向新节点
	newNode->tail = headNode;//新节点的后指针指向头节点
}
//3.指定位置插入
void insertNodeByAppoin(struct Node* headNode, int posData, int data)
{
	if (headNode->front == headNode && headNode->tail == headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("链表为NULL,无法插入\n");
	}
	else
	{
		struct Node* posFrontNode = headNode;
		struct Node* posNode = headNode->tail;
		while (posNode->data != posData)
		{
			posFrontNode = posNode;
			posNode = posNode->tail;
			while (posNode == headNode)
			{
				break;
			}
		}
		if (posNode == headNode)
		{
			printf("未找到指定位置,无法做指定位置插入\n");
		}
		else
		{
			struct Node* newNode = createNode(data);//创建节点
			//做连线,四条连线
			posFrontNode->tail = newNode;//指定位置前节点的后指针指向新节点
			newNode->front = posFrontNode;//新节点的前指针指向指定位置节点
			posNode->front = newNode;//指定位置节点的前指针指向新节点
			newNode->tail = posNode;//新节点的后指针指向指定位置节点
		}
	}
}
//删除
//4.头删除
void deleteNodeByHead(struct Node* headNode)
{
	if (headNode->front == headNode&&headNode->tail==headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("链表为NULL,无法进行删除\n");
	}
	else
	{
		struct Node* nextNode = headNode->tail;//记录一下第一个数据节点
		//做连接:头节点的尾指针指向nextNode的tail
		headNode->tail = nextNode->tail;
		//nextNode->tail的头指针指向headNode
		nextNode->tail->front = headNode;
		//清理第一个数据节点
		free(nextNode);
		nextNode = NULL;
	}
}
//5.尾删除
void deleteNodeByTail(struct Node* headNode)
{
	if (headNode->front == headNode && headNode->tail == headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("链表为NULL,无法进行删除。\n");
	}
	else
	{
		struct Node* tailNode = headNode->front;//找到尾节点,headNode的前指针就是尾节点
		tailNode->front->tail = headNode;
		headNode->front = tailNode->front;
		free(tailNode);
		tailNode = NULL;
	}
}
//指定位置删除
void deleteNodeByAppoin(struct Node* headNode, int posData)
{
	struct Node* posFrontNode = headNode;
	struct Node* posNode = headNode->tail;
	if (posNode->data == posData)//首个数据节点的数据等于指定数据时,头删除
	{
		deleteNodeByHead(headNode);
	}
	else
	{
		while (posNode->data != posData)
		{
			posFrontNode = posNode;
			posNode = posNode->tail;
			if (posNode == headNode)//循环一圈回到headNode,说明没有指定数据。退出
			{
				break;
			}
		}
		if (posNode == headNode)//判断posNode的状态
		{
			printf("没有找到指定数据,无法进行删除。\n");
		}
		else
		{
			posFrontNode->tail = posNode->tail;
			posNode->tail->front = posFrontNode;
			free(posNode);
			posNode = NULL;
		}
	}
}

//打印测试
//通过后指针打印遍历
void printListByTail(struct Node* headNode)
{
	if (headNode->front == headNode&&headNode->tail==headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("表为NULL,无法打印\n");
		return;
	}
	struct Node* pMove = headNode->tail;
	printf("通过后指针打印\n");
	while (pMove != headNode)
	{
		printf("%d ", pMove->data);
		pMove = pMove->tail;
	}
	printf("\n"); 
}
//通过前指针打印遍历
void printListByFront(struct Node* headNode)
{
	if (headNode->front == headNode&&headNode->tail==headNode)//当头指针和尾指针指向headNode时,说明为初始状态,链表为空。
	{
		printf("表为NULL,无法打印\n");
		return;
	}
	struct Node* pMove = headNode->front;
	printf("通过后指针打印\n");
	while (pMove != headNode)
	{
		printf("%d ", pMove->data);
		pMove = pMove->front;
	}
	printf("\n");
}
int main()
{
	//创建链表
	struct Node* list = createList();
	
	//尾插法
	insertNodeByTail(list, 3);
	insertNodeByTail(list, 2);
	insertNodeByTail(list, 1);
	printListByTail(list);
	printListByFront(list);
	printListByTail(list);

	//头插法
	insertNodeByFront(list, 4);
	insertNodeByFront(list, 5);
	insertNodeByFront(list, 6);
	printListByTail(list);

	//指定位置插入
	insertNodeByAppoin(list, 6, 7);
	printListByTail(list);

	//头删
	deleteNodeByHead(list);
	deleteNodeByHead(list);
	printListByTail(list);

	//尾删
	deleteNodeByTail(list);
	deleteNodeByTail(list);
	printListByTail(list);

	//指定位置删除
	deleteNodeByAppoin(list, 4);
	deleteNodeByAppoin(list, 3);
	deleteNodeByAppoin(list, 5);
	printListByTail(list);
	return 0;
}

未完持续更新数据结构……

发布了57 篇原创文章 · 获赞 12 · 访问量 3315

猜你喜欢

转载自blog.csdn.net/weixin_44795839/article/details/103229637