双向带头循环链表是最优链表,结构复杂,功能丰富是它的特性
今天,教大家实现一个双向带头循环链表哦,平常刷题时我们都是用的单向链表,因为功能简单具有考查性!而这个双向带头循环链表功能复杂,很多的题都在双向带头循环链表下都没有任何的考察性,哈哈哈,是一个比较完美的链表。
一般我们常见的是无头单向非循环列表,结构简单,一般不会用来单独存储数据,更多的是作为其他数据结构的子结构,如哈希桶,图的邻接表。
双向带头循环链表,常用于存储数据,结构复杂操作简单,但又一定的缺陷,如无法随机存取等。
顺序表与双向带头循环链表的区别
不同点 顺序表 链表 存储空间上 物理上一定连续 逻辑上连续,但物理上不一定连续 随机访问 支持 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 后查看