最完美的链表--双向带头循环链表

发布于:2022-11-07 ⋅ 阅读:(253) ⋅ 点赞:(0)

        双向带头循环链表是最优链表,结构复杂,功能丰富是它的特性 

        今天,教大家实现一个双向带头循环链表哦,平常刷题时我们都是用的单向链表,因为功能简单具有考查性!而这个双向带头循环链表功能复杂,很多的题都在双向带头循环链表下都没有任何的考察性,哈哈哈,是一个比较完美的链表。

        

         一般我们常见的是无头单向非循环列表,结构简单,一般不会用来单独存储数据,更多的是作为其他数据结构的子结构,如哈希桶,图的邻接表。

        双向带头循环链表,常用于存储数据,结构复杂操作简单,但又一定的缺陷,如无法随机存取等。

         

顺序表与双向带头循环链表的区别

不同点 顺序表 链表 存储空间上 物理上一定连续 逻辑上连续,但物理上不一定连续 随机访问 支持 O(1) 不支持:O(N) 任意位置插入或者删除元素 可能需要搬移元素,效率低 只需要修改指针指向 插入 动态顺序表,空间不够时需要 没有容量的概念 应用场景
元素高效存储+频繁访问
任意位置插入和删除频繁
缓存利用率 高 低

实现

List.c

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int LTDataType;

typedef struct ListNode
{
	struct ListNode* next;
	struct ListNode* prev;
	LTDataType data;
}LTNode;

void menu();

//void ListInit(LTNode** phead);
LTNode* ListInit();

void ListPushBack(LTNode* phead, LTDataType x);

void ListPrint(LTNode* phead);

void ListPushFront(LTNode* phead, LTDataType x);

void ListPopFront(LTNode* phead);
void ListPopBack(LTNode* phead);
bool ListEmpty(LTNode* phead);

void ListFrontInsert(LTNode* pos, LTDataType x);
void ListBackInsert(LTNode* pos, LTDataType x);

void ListErase(LTNode* pos);
int ListSize(LTNode* phead);

void ListDestory(LTNode* phead);
void ListModify(LTNode* phead, LTDataType x, LTDataType y);
LTNode* ListFind(LTNode* phead, LTDataType x);

List.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"



LTNode* BuyListNode(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;
}

//void ListInit(LTNode** pphead)
//{
//	*pphead = BuyListNode(-1);
//	(* pphead)->next = *pphead;
//	(* pphead)->prev = *pphead;
//}

void menu()
{
	printf("*****************************************************************\n");
	printf("1、尾插      2、头插\n");
	printf("3、尾删      4、头删\n");
	printf("5、前面插    6、后面插\n");
	printf("7、任意删    8、前删\n");
	printf("9、后删    10、修改\n");
	printf("11、打印     -1、退出\n");

	printf("*****************************************************************\n");

}

LTNode* ListInit()
{
	LTNode* phead = BuyListNode(-1);
	phead->next = phead;
	phead->prev = phead;
	return phead;
}
void ListPushBack(LTNode* phead, LTDataType x) {
	assert(phead);
	/*LTNode* newnode = BuyListNode(x);
	LTNode* tail = phead->prev;
	newnode->next = phead;
	newnode->prev = tail;
	tail->next = newnode;
	phead->prev = newnode;*/
	ListFrontInsert(phead, x);
}
void ListPrint(LTNode* phead){
	assert(phead);
	LTNode* cur = phead->next;
	while (cur!=phead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}
void ListPushFront(LTNode* phead, LTDataType x) {
	assert(phead);
	/*LTNode* newnode = BuyListNode(x);
	LTNode* head = phead->next;
	newnode->next = head;
	newnode->prev = phead;
	phead->next = newnode;
	head->prev = newnode;*/
	ListFrontInsert(phead->next, x);
}

void ListPopBack(LTNode* phead)
{
	assert(phead);
	assert(!ListEmpty(phead));
	LTNode* tail = phead->prev;
	tail->prev->next = phead;
	phead->prev = tail->prev;
	free(tail);
	//ListErase(phead->prev);
}
bool ListEmpty(LTNode* phead)
{
	assert(phead);
	return phead->next == phead;
}
void ListPopFront(LTNode* phead)
{
	assert(phead);
	assert(!ListEmpty(phead));
	LTNode* nexthead = phead->next;
	nexthead->next->prev = phead;
	phead->next = nexthead->next;
	free(nexthead);
	//ListErase(phead->next);
}
void ListFrontInsert(LTNode* pos, LTDataType x)
{
	LTNode* newnode = BuyListNode(x);
	LTNode* prev = pos->prev;
	newnode->next = pos;
	newnode->prev = prev;
	prev->next = newnode;
	pos->prev = newnode;
}
void ListBackInsert(LTNode* pos, LTDataType x)
{
	LTNode* newnode = BuyListNode(x);
	LTNode* next = pos->next;
	newnode->next = next;
	newnode->prev = pos;
	pos->next = newnode;
	next->prev = newnode;
}
void ListErase(LTNode* pos)
{
	assert(pos);
	LTNode* prev = pos->prev;
	LTNode* next = pos->next;
	prev->next = next;
	next->prev = prev;
	free(pos);

}
int ListSize(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	int size = 0;
	while (cur != phead)
	{
		++size;
		cur = cur->next;
	}
	return size;
}
void ListDestory(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		ListErase(cur);
		cur = next;
	}
	free(phead);
}
LTNode* ListFind(LTNode* phead, LTDataType x)
{
	assert(phead);
	if (phead == NULL)
	{
		return NULL;
	}
	for (LTNode* cur = phead->next; cur != phead; cur = cur->next) {
		if (cur->data == x) {
			return cur;
		}
	}

	return NULL;
}
void ListModify(LTNode* phead, LTDataType x, LTDataType y)
{
	LTNode* ret = ListFind(phead, x);
	if (ret)
	{
		ret->data = y;
	}
}

 First.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"List.h"
int main()
{
	LTNode* plist = ListInit();
	
	
	int option;
	do {
		menu();
		if (scanf("%d", &option) == EOF)
		{
			printf("scanf输入错误\n");
			break;
		}

		int val, pos;
		switch (option)
		{
		case -1:
			printf("退出\n");
			exit(0);
			break;
		case 1:
			printf("请连续输入你要尾插的数据,以0结束:\n");
			scanf("%d", &val);
			while (val != 0)
			{
				ListPushBack(plist, val);
				scanf("%d", &val);
			}
			break;
		case 2: {
			printf("请连续输入你要头插的数据,以0结束:\n");
			scanf("%d", &val);
			while (val != 0)
			{
				ListPushFront(plist, val);
				scanf("%d", &val);
			}
			break;
		}
		case 3:
			ListPopBack(plist);
			break;
		case 4:
			ListPopFront(plist);
			break;
		case 5:
		{
			int y;
			int x;
			printf("请输入你要的被插入的,和插入的值\n");
			scanf("%d%d", &x, &y);
			LTNode* pos = ListFind(plist, x);
			ListFrontInsert(pos, y);
			break;
		}
		case 6:
		{
			int y;
			int x;
			printf("请输入你要的被插入的,和插入的值\n");
			scanf("%d%d", &x, &y);
			LTNode* pos = ListFind(plist, x);
			ListBackInsert(pos, y);
			break;
		}
		case 7:
		{
			int x;
			printf("请输入你要删除的值\n");
			scanf("%d", &x);
			LTNode* pos = ListFind(plist, x);
			ListErase(pos);
			break;
		}
		case 8:
		{
			int x;
			printf("请输入你要删除的值\n");
			scanf("%d", &x);
			LTNode* pos = ListFind(plist, x);
			ListPopFront(pos);
			break;
		}
		case 9:
		{
			int x;
			printf("请输入你要删除的值\n");
			scanf("%d", &x);
			LTNode* pos = ListFind(plist, x);
			ListPopBack(pos);
			break;
		}
		case 10:
		{
			int y;
			int x;
			printf("请输入你要修改的位置,和修改后的值\n");
			scanf("%d%d", &x, &y);
			ListModify(plist, x, y);
			break;
		}
		case 11:
			ListPrint(plist);
			break;
		default:
			exit(-1);
			break;
		}
	} while (option != -1);
	ListDestory(plist);
	return 0;
}

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到