一.逻辑结构:

双向带头链表有一个数值域和两个指针域。一个头节点,前驱指向最后一个节点,后继指向第一个节点;每一个节点有一个前驱和一个后继,分别 指向前一个节点和后一个节点;链表的最后一个节点的后继指向链表的头节点。

二.功能:

双向带头链表中实现的功能有:初始化链表、头插、尾插、头删、尾删,在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;}
}

带头节点的双向带头循环链表相关推荐

  1. C语言实现双向非循环链表(不带头结点)的基本操作

    双向链表也叫双链表,它的每个数据节点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任何一个节点开始,都可以很方便的访问它的前驱结点和后继节点.别人常常来构造双向循环链表,今天我们特立 ...

  2. c语言循环链表中设立尾链表,C语言实现双向非循环链表(带头结点尾结点)的节点插入...

    对于双向链表,个人推荐使用带头结点尾结点的方式来处理会比较方便.我在<C语言实现双向非循环链表(不带头结点)的节点插入>中详细实现了在不带头结点的情况下的插入.这次我们将会来在使用头结点尾 ...

  3. 数据结构-线性表之带头结点的双向循环链表

    文章目录 前言 实现 (1)结构定义 (2)基本函数 (3)操作实现 测试 代码 前言 链表的类型有很多种(根据带头或不带头,循环或非循环等等),但是我们重点研究的只有两种,一种结构非常简单是无头单向 ...

  4. 链表界的“扛把子”—双向带头循环链表

    目录 一:链表的分类 二:链表的实现 2-1:创建链表 2-2:创建新的结点 2-3:初始化链表 2-4:打印链表 2-5:销毁链表 三:链表的核心功能 3-1:尾插 3-2:尾删 3-3:链表查找 ...

  5. 双向带头循环链表的(增删查改)的实现

    文章目录 一.双向带头循环链表 构成 二.双向带头循环链表的实现 1.函数的定义和结构体的创建--list.h 2.函数的调用--list.c 3. 双向带头循环链表与单链表的传递参数区别 4.双向带 ...

  6. 数据结构------双向带头循环链表

    目录 1.什么是双向带头循环链表?模型. 2.1 创建结点函数 2.2初始化 3.尾插实现 3.1图示 3.2尾插 4.打印函数实现 4.1打印函数 5.思考为啥是一级指针 6.头插实现 6.2实现代 ...

  7. 双向带头循环链表的实现

    双向带头循环链表 双向带头循环链表 结构讲解 期望实现功能 创建链表和头节点作用 头插和头删 头插 头删 尾插与尾删 尾插 尾删 pos 删除和插入 插入 删除 打印和查找 整体代码 这个数据结构可以 ...

  8. 外强中干——双向带头循环链表

    前言:众所周知,链表有八种结构,由单向或双向,有头或无头,循环或不循环构成.在本篇,将介绍8种链表结构中最复杂的--双向带头循环链表.听着名字或许挺唬人的,但实际上双向带头循环链表实现起来比结构最简单 ...

  9. 【双向带头循环链表】

    双向带头循环链表 0.链表中每个节点的基本结构 1.初始化链表(创建哨兵位头节点) 2.申请新节点 3.尾插节点 4.尾删节点 5.头插节点 6.头删节点 7.寻找pos位置的节点 8.在pos位置之 ...

最新文章

  1. c语言一行黑白相间的瓷砖,C语言编程练习15:贴瓷砖
  2. 《CCNP TSHOOT 300-135认证考试指南》——2.2节故障检测与排除及网络维护工具箱
  3. closewait一直不释放_家里甲醛一直去不掉,原来是原理弄错了!跟邻居学来这一招搞定...
  4. SQL XQuery的Action
  5. 动态编译MySQL plugin
  6. 老司机实战Windows Server Docker:3 单节点Windows Docker服务器简单运维(上)
  7. Windows To Ghost系统封装之必备软件集 - 好压
  8. TableAdapter和DataAdapter有何区别
  9. 2020.7.20-每日进步
  10. C++ STL 遍历vector
  11. matlab读取jpg图片出错,求助,Matlab读取图片进行分类。出现错误
  12. 守望先锋归来(守望先锋2)游戏笔记
  13. Peer Manager
  14. 【使用心得】ChatGPT做出行攻略
  15. Windows 8 引入新版的凭据管理器
  16. OpenCV开发笔记(五十一):红胖子8分钟带你深入了解透视变换(图文并茂+浅显易懂+程序源码)
  17. 《STL源码剖析》-- stl_map.h
  18. 《软件定义数据中心:Windows Server SDDC技术与实践》一导读
  19. 3.1 Go语言中的函数与方法
  20. linux文本文件导入数据库,Linux系统下如何将txt文档导入到数据库mysql的方法教程...

热门文章

  1. 数据库版本控制工具介绍
  2. aws lambda_我如何在一天内在Node.js中构建无服务器的AWS Lambda Twitter机器人
  3. Ubuntu系统下C语言的简单使用及gcc和Makefile编译C程序
  4. Android Studio编写代码无错误提示问题
  5. 【程序2】题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%;20
  6. 在Photoshop中创建碳纤维图案
  7. 【定量分析、量化金融与统计学】纵向数据分析(1)——截面数据、时间序列数据和纵向数据
  8. 键盘控制husky小车移动
  9. angular英雄教程学习
  10. 解决mac无法打开共享的问题