0
点赞
收藏
分享

微信扫一扫

【数据结构第二讲(链表中的老大哥----带头双向循环链表)】

没关系,我们今天就来学习一种更加完善的方法!
精彩预告:这种方法可谓是目前所有链表中优点最多,缺点最少的了❗️❗️❗️

打起精神,开始学习吧!💪💪💪

文章目录

一、🏆链表的分类

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构

1.1🏅带头或不带头

在这里插入图片描述

在这里插入图片描述

1.2🏅单向或双向

在这里插入图片描述

1.3🏅循环或非循环

在这里插入图片描述

二、🏆带头双向循环链表的优点

先来看一下带头双向循环链表的结构:👇👇👇

在这里插入图片描述

接下来,就一起在接口的实现过程中体验它的优点吧🔥🔥🔥

三、🏆带头双向循环链表接口的实现

先来看一下接口实现索要包含的头文件、结构体定义和具体函数的声明👇👇👇

#define _CRT_SECURE_NO_WARNINGS
#pragma once

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

typedef int LTDataType;

typedef struct ListNode
{
	LTDataType data;//存储有效数据
	struct ListNode* prev;//存储上一个结点的地址
	struct ListNode* next;//存储下一个结点的地址
}ListNode;

//链表的初始化
ListNode* ListInit();
//打印链表内容
void ListPrint(ListNode* phead);
//创建结点
ListNode* CreateNode(LTDataType x);
//尾插
void ListPushBack(ListNode* phead, LTDataType x);
//尾删
void ListPopBack(ListNode* phead);
//头插
void ListPushFront(ListNode* phead, LTDataType x);
//头删
void ListPopFront(ListNode* phead);
//在指定位置插入
void ListInsert(ListNode* pos, LTDataType x);
//在指定位置删除
void ListErase(ListNode* pos);
//查找
void ListFind(ListNode* phead, LTDataType x);
//链表的销毁
void ListDestory(ListNode* phead);
//退出程序
void Exit(ListNode* phead);

3.1🏅链表的初始化

在这里插入图片描述

ListNode* ListInit()
{
	//为哨兵位开辟空间
	ListNode* phead = (ListNode*)malloc(sizeof(ListNode));
	if (phead == NULL)
	{
		printf("malloc failed!\n");
		return;
	}
	else
	{
		phead->next = phead;//哨兵位的next和prev都指向自己,形成循环结构
		phead->prev = phead;
	}
}

3.2🏅创建新的结点

ListNode* CreateNode(LTDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		printf("malloc failed!\n");
		return;
	}
	newnode->data = x;
	return newnode;
}

创建结点完毕之后,要将该结点返回,以便可以将该结点尾插到链表的最后。

3.3🏅打印链表内容

在这里插入图片描述

void ListPrint(ListNode* phead)
{
	assert(phead);
	if (phead->next == phead)
	{
		printf("链表为空!\n");
		return;
	}
	ListNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

3.4🏅链表的头插

在这里插入图片描述

void ListPushFront(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListNode* newnode = CreateNode(x);
	newnode->next = phead->next;
	phead->next->prev = newnode;
	newnode->prev = phead;
	phead->next = newnode;
	printf("头插成功!\n");
}

3.5🏅链表的头删

在这里插入图片描述

void ListPopFront(ListNode* phead)
{
	assert(phead);
	if (phead->next == phead)
	{
		printf("链表为空!\n");
		return;
	}
	ListNode* newfirst = phead->next->next;
	free(phead->next);
	phead->next = NULL;
	phead->next = newfirst;
	newfirst->prev = phead;
	printf("头删成功!\n");
}

3.6🏅链表的尾插

在这里插入图片描述

void ListPushBack(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListNode* newnode = CreateNode(x);
	newnode->prev = phead->prev;
	phead->prev->next = newnode;
	newnode->next = phead;
	phead->prev = newnode;
	printf("尾插成功!\n");
}

3.7🏅链表的尾删

在这里插入图片描述

void ListPopBack(ListNode* phead)
{
	assert(phead);
	if (phead->next == phead)
	{
		printf("链表为空!\n");
		return;
	}
	ListNode* tail = phead->prev;
	phead->prev = tail->prev;
	tail->prev->next = phead;
	free(tail);
	tail = NULL;
	printf("尾删成功!\n");
}

3.8🏅在指定位置插入

void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos);
	ListNode* newnode = CreateNode(x);
	ListNode* posprev = pos->prev;
	pos->prev = newnode;
	newnode->next = pos;
	newnode->prev = posprev;
	posprev->next = newnode;
	printf("插入成功!\n");
}

3.9🏅在指定位置删除

void ListErase(ListNode* pos)
{
	assert(pos);
	ListNode* posnext = pos->next;
	ListNode* posprev = pos->prev;
	posnext->prev = posprev;
	posprev->next = posnext;
	free(pos);
	pos = NULL;
	printf("删除成功!\n");
}

3.10🏅在链表中查找

void ListFind(ListNode* phead, LTDataType x)
{
	assert(phead);
	if (phead->next == phead)
	{
		printf("链表为空!\n");
		return;
	}
	ListNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			printf("找到了!\n");
			return;
		}
		cur = cur->next;
	}
	printf("没找到!\n");
}

3.11🏅链表的销毁

void ListDestory(ListNode* phead)
{
	assert(phead);
	free(phead);
	phead = NULL;
	printf("销毁成功!\n");
}

四、总结

加油吧❗️❗️❗️

举报

相关推荐

0 条评论