【数据结构】——带头双向循环链表
创始人
2024-03-12 14:17:20
0

目录

1.带头双向循环链表

2.链表实现

2.1可完成带头双向可循环链表节点的结构体

2.2申请一个可双向循环的节点

2.3初始化链表

2.4尾插

2.5尾删

2.6头插

2.7头删

2.8打印

2.9查找(修改)

2.10在pos之前插入x

2.11删除pos位置

 2.12判空

2.13记录链表大小

2.14销毁

3.完整的带头双向循环链表代码

3.1——List.h

3.2——List.c


1.带头双向循环链表

对比:

我们实际中最常用还是两种链表结构: 1.无头单向非循环链表

用处: 

结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构, 如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。 2.带头双向循环链表

 用处:

结构在链表中最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,反而使得实现功能更简单了。

2.链表实现

2.1可完成带头双向可循环链表节点的结构体

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

2.2申请一个可双向循环的节点

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;
}

2.3初始化链表

LTNode* ListInit()
{LTNode* phead = BuyListNode(-1);phead->next = phead;phead->prev = phead;return phead;
}

2.4尾插

void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);//方法1/*LTNode* newnode = BuyListNode(x);LTNode* tail = phead->prev;tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;*///方法2LTInsert(phead, x);
}

2.5尾删

void LTPopBack(LTNode* phead)
{assert(phead);assert(phead->next != phead);  // 空//方法1//LTNode* tail = phead->prev;//LTNode* tailPrev = tail->prev;//tailPrev->next = phead;//phead->prev = tailPrev;//free(tail);//方法2LTErase(phead->prev);
}

2.6头插

void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);//方法1(有关顺序)/*LTNode* newnode = BuyListNode(x);newnode->next = phead->next;phead->next->prev = newnode;phead->next = newnode;newnode->prev = phead;*///方法2(无关顺序)//LTNode* newnode = BuyListNode(x);//LTNode* first = phead->next;phead newnode first 顺序无关//phead->next = newnode;//newnode->prev = phead;//newnode->next = first;//first->prev = newnode;//方法3LTInsert(phead->next, x);}

2.7头删

void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead); // 空//方法1/*LTNode* first = phead->next;LTNode* second = first->next;free(first);phead->next = second;second->prev = phead;*///方法2LTErase(phead->next);
}

2.8打印

void LTPrint(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");
}

2.9查找(修改)

LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}

2.10在pos之前插入x

 

// 在pos之前插入x
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* prev = pos->prev;LTNode* newnode = BuyListNode(x);// prev newnode posprev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}

2.11删除pos位置

// 删除pos位置
void LTErase(LTNode* pos)
{assert(pos);LTNode* prev = pos->prev;LTNode* next = pos->next;free(pos);prev->next = next;next->prev = prev;
}

 2.12判空

bool LTEmpty(LTNode* phead)
{assert(phead);/*if (phead->next == phead){return true;}else{return false;}*/return phead->next == phead;
}

2.13记录链表大小

size_t LTSize(LTNode* phead)
{assert(phead);size_t size = 0;LTNode* cur = phead->next;while (cur != phead){++size;cur = cur->next;}return size;
}

2.14销毁

void LTDestroy(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;free(cur);      cur = next;}free(phead);//phead = NULL;
}

3.完整的带头双向循环链表代码

3.1——List.h

#pragma once#include 
#include 
#include 
#include //typedef char LTDataType;
//typedef double LTDataType;
typedef int LTDataType;typedef struct ListNode
{struct ListNode* next;struct ListNode* prev;LTDataType data;
}LTNode;//创建节点
LTNode* BuyListNode(LTDataType x);
//初始化
LTNode* LTInit();//打印
void LTPrint(LTNode* phead);
//尾插尾删
void LTPushBack(LTNode* phead, LTDataType x);
void LTPopBack(LTNode* phead);
//头插头删
void LTPushFront(LTNode* phead, LTDataType x);
void LTPopFront(LTNode* phead);
//查找
LTNode* LTFind(LTNode* phead, LTDataType x);// pos前面插入
void LTInsert(LTNode* pos, LTDataType x);
// pos位置删除
void LTErase(LTNode* pos);
//判空
bool LTEmpty(LTNode* phead);
//大小
size_t LTSize(LTNode* phead);
//销毁
void LTDestroy(LTNode* phead);

3.2——List.c

#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;
}LTNode* LTInit()
{LTNode* phead = BuyListNode(-1);phead->next = phead;phead->prev = phead;return phead;
}void LTPrint(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");
}void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);//方法1/*LTNode* newnode = BuyListNode(x);LTNode* tail = phead->prev;tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;*///方法2LTInsert(phead, x);
}void LTPopBack(LTNode* phead)
{assert(phead);assert(phead->next != phead);  // 空//方法1//LTNode* tail = phead->prev;//LTNode* tailPrev = tail->prev;//tailPrev->next = phead;//phead->prev = tailPrev;//free(tail);//方法2LTErase(phead->prev);
}void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);//方法1(有关顺序)/*LTNode* newnode = BuyListNode(x);newnode->next = phead->next;phead->next->prev = newnode;phead->next = newnode;newnode->prev = phead;*///方法2(无关顺序)//LTNode* newnode = BuyListNode(x);//LTNode* first = phead->next;phead newnode first 顺序无关//phead->next = newnode;//newnode->prev = phead;//newnode->next = first;//first->prev = newnode;//方法3LTInsert(phead->next, x);}void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead); // 空//方法1/*LTNode* first = phead->next;LTNode* second = first->next;free(first);phead->next = second;second->prev = phead;*///方法2LTErase(phead->next);
}LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}// 在pos之前插入x
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* prev = pos->prev;LTNode* newnode = BuyListNode(x);// prev newnode posprev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}// 删除pos位置
void LTErase(LTNode* pos)
{assert(pos);LTNode* prev = pos->prev;LTNode* next = pos->next;free(pos);prev->next = next;next->prev = prev;
}//判空
bool LTEmpty(LTNode* phead)
{assert(phead);/*if (phead->next == phead){return true;}else{return false;}*/return phead->next == phead;
}size_t LTSize(LTNode* phead)
{assert(phead);size_t size = 0;LTNode* cur = phead->next;while (cur != phead){++size;cur = cur->next;}return size;
}void LTDestroy(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;free(cur);      cur = next;}free(phead);//phead = NULL;
}

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...