【数据结构】双向链表实现
Yan-英杰的主页
悟已往之不谏 知来者之可追
C++程序员,2024届电子信息研究生
目录
一、什么是双向链表
二、双向链表的实现
一、什么是双向链表
双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
二、双向链表的实现
List.h
#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;LTNode* LTInit();
void LTDestory(LTNode* phead);
void LTPrint(LTNode* phead);
bool LTEmpty(LTNode * phead);
void LTPushBack(LTNode* phead,LTDataType x);
void LTPopBack(LTNode * phead);void LTPushFront(LTNode *phead,LTDataType x);
void LTPopFront(LTNode* phead);void LTInsert(LTNode* pos,LTDataType x);
void LTErase(LTNode* pos);
LTNode* LTFind(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("fail:malloc");exit(-1);}node->next = NULL;node->prev = NULL;node->data = x;return node;
}LTNode* LTInit()
{LTNode* phead = BuyListNode(-1);phead->next = phead;phead->prev = phead;return phead;
}
bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead;
}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;
}
void LTPrint(LTNode* phead)
{assert(phead);printf("<=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);LTInsert(phead,x);
}void LTPopBack(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTErase(phead->prev);
}void LTPushFront(LTNode* phead,LTDataType x)
{assert(phead);LTInsert(phead->next,x);
}void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTErase(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前一个位置添加节点
void LTInsert(LTNode* pos,LTDataType x)
{assert(pos);LTNode* prev = pos->prev;LTNode* newnode = BuyListNode(x);prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}void LTErase(LTNode* pos)
{assert(pos);LTNode* p = pos->prev;LTNode* n = pos->next;p->next = n;n->prev = p;free(pos);pos = NULL;
}
思路:
BuyListNode函数
BuyListNode的实现,我们在实现头插尾插时,为了更加遍历的实现功能,我们创建了BuyListNode函数,malloc一块新的空间,并且对其进行初始化,返回其类型
LTNode* BuyListNode(LTDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("fail:malloc");exit(-1);}node->next = NULL;node->prev = NULL;node->data = x;return node;
}
LTInit函数
在实现该链表前,我们对其进行初始化,对其哨兵位的头节点,进行循环指向
哨兵位头节点的出现,使得链表添加与删除效率大大提高
LTNode* LTInit()
{LTNode* phead = BuyListNode(-1);phead->next = phead;phead->prev = phead;return phead;
}
LTInsert和LTErase函数
LTInsert函数的实现:
我们找到pos的前一个节点位置,进行操作,首先我们找到pos的前一个位置,保存该节点,创建新的节点,将pos前一个位置的节点next指向新节点,新节点的prev指向pos前一个位置,新节点的next指向pos,pos的前一个位置指向新节点
LTErase函数的实现:
删除pos位置的节点,先暴力检查是否为空,其中只有哨兵位的头节点,如果只有头节点则直接报错,保存pos位置节点的前一个节点和后一个节点,让pos的prev和next分别指向前一个位置和后一个位置的节点
void LTInsert(LTNode* pos,LTDataType x)
{assert(pos);LTNode* prev = pos->prev;LTNode* newnode = BuyListNode(x);prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}void LTErase(LTNode* pos)
{assert(pos);LTNode* p = pos->prev;LTNode* n = pos->next;p->next = n;n->prev = p;free(pos);pos = NULL;
}
LTPushBack与LTPopBack函数
尾插与尾删功能,我们先对其进行暴力检查,通过LTInsert和LTErase函数进行实现该功能
void LTPushBack(LTNode* phead,LTDataType x)
{ assert(phead);LTInsert(phead,x);
}void LTPopBack(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTErase(phead->prev);
}
LTPushFront和LTPopFront函数
头插与头删功能,我们先对其进行暴力检查,通过LTInsert和LTErase函数进行实现该功能
void LTPushFront(LTNode* phead,LTDataType x)
{assert(phead);LTInsert(phead->next,x);
}void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTErase(phead->next);
}
LTDestory和LTPrint函数的实现
LTPrint: 当我们功能实现时,LTPrint函数可在控制台进行打印和输出,优先找到哨兵位头节点的下一位,我们对其进行循环,当循环节点等于哨兵位时,停止循环
LTDestory:当我们退出链表时,对其进行销毁
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;
}
void LTPrint(LTNode* phead)
{assert(phead);printf("<=phead=>");LTNode* cur = phead->next;while (cur != phead){printf("%d<=>",cur->data);cur = cur->next;}printf("\n");
}
ListTest.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "List.h"
void ListTest()
{LTNode* phead = LTInit();LTPushBack(phead, 1);LTPushBack(phead, 2);LTPushBack(phead, 3);LTPrint(phead);LTPopBack(phead);LTPrint(phead);LTPushFront(phead,10);LTPrint(phead);LTPopFront(phead);LTPrint(phead);
}int main()
{ListTest();return 0;
}
【数据结构】双向链表实现相关推荐
- 数据结构 — 双向链表
目录 文章目录 目录 双向链表 双向链表结点的数据结构 双向链表的操作集合 应用示例 创建双向链表 清理双向链表 查询链表结点 更新链表结点的数据 插入链表结点 删除结点 打印链表数据 双向链表 双向 ...
- 数据结构 —— 双向链表(超详细图解 接口函数实现)
系列文章目录 数据结构 -- 顺序表 数据结构 -- 单链表 数据结构 -- 双向链表 数据结构 -- 队列 数据结构 -- 栈 数据结构 -- 堆 数据结构 -- 二叉树 数据结构 -- 八大排序 ...
- python 双向链表_数据结构-双向链表(Python实现)
数据结构在编程世界中一直是非常重要的一环,不管是开发还是算法,哪怕是单纯为了面试,数据结构都是必修课,今天我们介绍链表中的一种--双向链表的代码实现. 好了,话不多说直接上代码. 双向链表 首先,我们 ...
- python程序实现双向链表_数据结构-双向链表(Python实现)
数据结构在编程世界中一直是非常重要的一环,不管是开发还是算法,哪怕是单纯为了面试,数据结构都是必修课,今天我们介绍链表中的一种--双向链表的代码实现. 好了,话不多说直接上代码. 双向链表 首先,我们 ...
- Linux c 算法与数据结构--双向链表
链表是linux c中非常重要的数据结构,双向链表与单向链表的区别,是它每个节点有两个指针域,分别指向该节点的前一个节点与后一个节点: 而链表的操作主要是查询.插入.删除.遍历等,下面来看一个双向链表 ...
- C语言数据结构双向链表之温故而知新
单向链表:http://blog.csdn.net/morixinguan/article/details/77756216 单向链表理解了,那双向就非常简单了,没什么好说的,看图: 双链表的引入是为 ...
- 数据结构 | 双向链表
一.数据结构定义 /* 链表结点 */ typedef int ListType; typedef struct node {ListType data; // 存放整型数据struct node* ...
- Linux内核分析--内核中的数据结构双向链表续【转】
在解释完内核中的链表基本知识以后,下面解释链表的重要接口操作: 1. 声明和初始化 实际上Linux只定义了链表节点,并没有专门定义链表头,那么一个链表结构是如何建立起来的呢?让我们来看看LIST_H ...
- 数据结构-双向链表的实现
题目: 1 双向升序链表结构定义如下: 2 class Node { 3 4 private int value;// 保存节点的数据 5 6 private Node pre, next;// 保存 ...
- 数据结构--双向链表
双向链表的一种Go语言实现 package mainimport "fmt"//定义节点信息 type dNode struct {id intname stringpre *dN ...
最新文章
- python科学计算基础教程pdf下载-用Python做科学计算 pdf版
- DL之AlexNet:AlexNet算法的架构详解、损失函数、网络训练和学习之详细攻略
- 从电源问题出发,带你揭秘新体系结构范式 COA
- 字节(byte)简介
- USACO 2.4.1 The Tamworth Two
- python中常见的漏洞_Python 中的 10 个常见安全漏洞,以及如何避免(上)
- TreeView控件 1202
- TensorFlow十三 LSTM练习
- 【伙伴故事】一盏智能灯,点亮家庭和工业照明的新未来
- Django发送邮件
- NSString属性什么时候用copy,什么时候用strong?【转】
- 【Luogu】P1486郁闷的出纳员(Splay)
- You have tried to change the API from what has been previously approved
- iOS 通讯录编程【总结】
- 监控与分析工具nmon的安装与使用
- 2寸的照片长宽各是多少_2寸照片的尺寸,1寸和 2 寸相片具体大小尺寸是多
- 近期互联网公司大量裁员,这给计算机er带来哪些启示?
- 简单html实现图片轮播,JavaScript实现简易轮播图
- 回环接口(loop-back/loopback)
- word2010中“不包含”、“不存在”等特殊字符的输入方法