带头节点的双向带头循环链表
一.逻辑结构:
双向带头链表有一个数值域和两个指针域。一个头节点,前驱指向最后一个节点,后继指向第一个节点;每一个节点有一个前驱和一个后继,分别 指向前一个节点和后一个节点;链表的最后一个节点的后继指向链表的头节点。
二.功能:
双向带头链表中实现的功能有:初始化链表、头插、尾插、头删、尾删,在pos位置之前插入一个节点、删除pos位置的节点
三.链表的结构
#define LTDataType int;
typedef struct ListNode
{//数值域LTDataType data;
//指针域(后继)struct ListNode* next;
//指针域(前驱)struct ListNode* prev;
}ListNode;
四.头文件声明
#pragma once
//带头双向链表,在任意位置插入删除的时间复杂度都是O(1),查找时为O(N)
#include<assert.h>
#include<stdio.h>
typedef int LTDataType;typedef struct ListNode
{struct ListNode* prev;struct ListNode* next;LTDataType data;
}ListNode;//初始化
ListNode* ListInit();
//销毁链表
void ListDestory(ListNode* plist);
//打印
void ListPrint(ListNode* plist);
//尾插
void ListPushBack(ListNode* plist, LTDataType x);
//头插
//void ListPushFront(ListNode* plist, LTDataType x);
void ListPushFront(ListNode* plist, LTDataType x);
//尾删
void ListPopBack(ListNode* phead);
//头删
void ListPopFront(ListNode* phead);
//开辟空间
ListNode* BuyListNode(LTDataType x);
//查找
ListNode* ListFind(ListNode* phead, LTDataType x);
//在pos位置之前插入x
void ListInsert(ListNode* pos, LTDataType x);
//删除pos位置的值
void ListErase(ListNode* pos);
//头插尾插,头删尾删都可以调用ListEnrase和ListInsert来实现
五.功能的实现:
**1. 开辟空间:**在实现其他功能之前,我们首先要开辟空间来存放链表的节点
ListNode* BuyListNode(LTDatatype x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));//将节点的数值域赋值为xphead->data = x;//将节点的前驱和后继置空phead->next = NULL;phead->prev = NULL;return newnode;
}
2.初始化链表:
我们需要在初始化中生成一个头节点,可以使用传参或返回值的方式得到头结点的地址
这里使用的是返回值的方式。
ListNode* ListInit()
{//将头结点的数值域赋值为0,并且将其前驱后继置空ListNode* phead = BuyListNode(0);phead->next = NULL;phead->prev = NULL;return phead;
}
3.查找:
这个功能可以帮助我们找到节点的地址,也能帮助我们实现其他功能
//找到时返回cur,cur为数值x所在的节点的地址;没有找到或链表为空时返回NULL
ListNode* ListFind(ListNode* phead,TLDatatype x)
{assert(phead);//cur的地址为第一个节点的地址ListNode* cur = phead->next;/*当cur==phead时,链表已经被遍历了一次,没有找到,返回NULL;链表若为空,则返回NULL*/while(cur->next !=phead){if(cur->data == x){return cur;}cur = cur->next;}return NULL;}
4. 在pos位置之前插入一个节点:
我们先实现这个功能;头插的功能可以使用这段代码实现。
逻辑表示:
//pos为使用查找功能ListFind返回的地址
void ListInsert(ListNode* pos,LTDatatype x)
{assert(pos);ListNode* newnode = BuyListNode(x);pos->prev = prev;prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}
5. 删除pos位置的节点:
逻辑表示:
ListNode* ListErase(ListNode* pos)
{assert(pos);ListNode* next= pos->next;ListNodde* prev = pos->prev;prev->next = next;next->prev = prev;free(pos);pos=NULL;
}
6.头插:头插可以使用ListFinde和ListInsert辅助实现:
(1)基本实现:
void ListPushFront(ListNode* phead,LTDatatype x)
{ListNode* newnode = BuyListNode(x);ListNode* next = phead->next;newnode->prev = phead;newnode->next = next;next->prev = newnode;phead->next = newnode;}
(2)ListInsert辅助实现:
//先使用ListFind找到第一个节点的位置pos
void ListPushFront(ListNode* phead,LTDataType x)
{ListNode* pos = phead->next;ListInsert(pos, x);
}
7. 尾插:
(1)基本实现:
void ListPushBack(ListNode* phead, LTDataType x)
{assert(phead);ListNode* tail = phead->prev;ListNode* newnode = BuyListNode(x);tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;//在有头节点的情况下,即使链表中只有一个头节点,尾插也可以顺利进行。
}
(2)ListInsert辅助实现:
//如果通过调用ListInsert来实现尾插,则需要将pos设定在头节点的位置
void ListPushBack(ListNode* phead, LTDataType x)
{ListNode* pos = phead;ListInsert(pos, x);
}
8.头删
(1)基本实现:
void ListPopFront(ListNode* phead)
{assert(phead;)//判断链表是否为空if(phead->next !=phead){//first为第一个节点,second为第二个节点ListNode* first=phead->next;ListNode* second = first->next;phead->next=second;second->prev=phead;}else{printf("链表为空,删除失败");}free(first);first=NULL;}
逻辑表示:
(2)利用ListErase辅助实现:
void ListPopFront(ListNode* phead)
{assert(phead);if (phead->next == phead){printf("链表为空");}else{ListNode* pos = phead->next;ListErase(pos);}
}
9.尾删
(1)基本实现:
void ListPopBack(ListNode* phead){assert(phead);if(phead->next !=phead){ListNode* last = phead->prev;ListNode* last2 = last->prev;last2->next = phead;phead->prev = last2;free(last);last=NULL;}}
(2)利用ListErase实现:
void ListPopBack(ListNode* phead)
{assert(phead);if(phead->next !=phead){ListNode* pos = phead->prev;ListErase(pos);}
}
10.销毁链表:
void ListDestory(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while(cur !=phead){ListNode* next = cur->next;free(cur);cur = next;}free(phead);phaed=NULL;printf("链表销毁成功");
}
11.打印链表:
void ListPrint(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while(cur != phead){printf("%d ",cur->data);cur = cur->next;}
}
带头节点的双向带头循环链表相关推荐
- C语言实现双向非循环链表(不带头结点)的基本操作
双向链表也叫双链表,它的每个数据节点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任何一个节点开始,都可以很方便的访问它的前驱结点和后继节点.别人常常来构造双向循环链表,今天我们特立 ...
- c语言循环链表中设立尾链表,C语言实现双向非循环链表(带头结点尾结点)的节点插入...
对于双向链表,个人推荐使用带头结点尾结点的方式来处理会比较方便.我在<C语言实现双向非循环链表(不带头结点)的节点插入>中详细实现了在不带头结点的情况下的插入.这次我们将会来在使用头结点尾 ...
- 数据结构-线性表之带头结点的双向循环链表
文章目录 前言 实现 (1)结构定义 (2)基本函数 (3)操作实现 测试 代码 前言 链表的类型有很多种(根据带头或不带头,循环或非循环等等),但是我们重点研究的只有两种,一种结构非常简单是无头单向 ...
- 链表界的“扛把子”—双向带头循环链表
目录 一:链表的分类 二:链表的实现 2-1:创建链表 2-2:创建新的结点 2-3:初始化链表 2-4:打印链表 2-5:销毁链表 三:链表的核心功能 3-1:尾插 3-2:尾删 3-3:链表查找 ...
- 双向带头循环链表的(增删查改)的实现
文章目录 一.双向带头循环链表 构成 二.双向带头循环链表的实现 1.函数的定义和结构体的创建--list.h 2.函数的调用--list.c 3. 双向带头循环链表与单链表的传递参数区别 4.双向带 ...
- 数据结构------双向带头循环链表
目录 1.什么是双向带头循环链表?模型. 2.1 创建结点函数 2.2初始化 3.尾插实现 3.1图示 3.2尾插 4.打印函数实现 4.1打印函数 5.思考为啥是一级指针 6.头插实现 6.2实现代 ...
- 双向带头循环链表的实现
双向带头循环链表 双向带头循环链表 结构讲解 期望实现功能 创建链表和头节点作用 头插和头删 头插 头删 尾插与尾删 尾插 尾删 pos 删除和插入 插入 删除 打印和查找 整体代码 这个数据结构可以 ...
- 外强中干——双向带头循环链表
前言:众所周知,链表有八种结构,由单向或双向,有头或无头,循环或不循环构成.在本篇,将介绍8种链表结构中最复杂的--双向带头循环链表.听着名字或许挺唬人的,但实际上双向带头循环链表实现起来比结构最简单 ...
- 【双向带头循环链表】
双向带头循环链表 0.链表中每个节点的基本结构 1.初始化链表(创建哨兵位头节点) 2.申请新节点 3.尾插节点 4.尾删节点 5.头插节点 6.头删节点 7.寻找pos位置的节点 8.在pos位置之 ...
最新文章
- c语言一行黑白相间的瓷砖,C语言编程练习15:贴瓷砖
- 《CCNP TSHOOT 300-135认证考试指南》——2.2节故障检测与排除及网络维护工具箱
- closewait一直不释放_家里甲醛一直去不掉,原来是原理弄错了!跟邻居学来这一招搞定...
- SQL XQuery的Action
- 动态编译MySQL plugin
- 老司机实战Windows Server Docker:3 单节点Windows Docker服务器简单运维(上)
- Windows To Ghost系统封装之必备软件集 - 好压
- TableAdapter和DataAdapter有何区别
- 2020.7.20-每日进步
- C++ STL 遍历vector
- matlab读取jpg图片出错,求助,Matlab读取图片进行分类。出现错误
- 守望先锋归来(守望先锋2)游戏笔记
- Peer Manager
- 【使用心得】ChatGPT做出行攻略
- Windows 8 引入新版的凭据管理器
- OpenCV开发笔记(五十一):红胖子8分钟带你深入了解透视变换(图文并茂+浅显易懂+程序源码)
- 《STL源码剖析》-- stl_map.h
- 《软件定义数据中心:Windows Server SDDC技术与实践》一导读
- 3.1 Go语言中的函数与方法
- linux文本文件导入数据库,Linux系统下如何将txt文档导入到数据库mysql的方法教程...
热门文章
- 数据库版本控制工具介绍
- aws lambda_我如何在一天内在Node.js中构建无服务器的AWS Lambda Twitter机器人
- Ubuntu系统下C语言的简单使用及gcc和Makefile编译C程序
- Android Studio编写代码无错误提示问题
- 【程序2】题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%;20
- 在Photoshop中创建碳纤维图案
- 【定量分析、量化金融与统计学】纵向数据分析(1)——截面数据、时间序列数据和纵向数据
- 键盘控制husky小车移动
- angular英雄教程学习
- 解决mac无法打开共享的问题