双向链表-

链表特性:带头/不带头

                  循环/非循环

--->排列组合后,共有8种链表结构

一.双向链表的定义

前一个节点存了后一个节点的地址,后一个节点也存了前一个节点的地址,即循环链表

二.代码解析

//双向链表
//与非循环链表区别!该双向链表事先设置了一个哨兵位节点,所以不用传入二级指针,即可改变链表里面的内容
#include <iostream>
#include <stdlib.h>
#include <assert.h>
using namespace std;
//1.定义链表结构
typedef int LTDateType;//适用于多类型(eg:int)
typedef struct ListNode
{LTDateType data;//链表中储存的数据struct ListNode* prev;//指向节点的前一个节点struct ListNode* next;//指向节点的后一个节点
}LTNode;
//2.初始化链表
//法1,传入二级指针,同非循环链表,即void ListInit(LTNode**pphead);
//法2,设置哨兵位头节点
LTNode* ListInit()
{//设置哨兵位头节点LTNode* phead = (LTNode*)malloc(sizeof(LTNode));//循环链表phead->next = phead;phead->prev = phead;return phead;
}
//3.打印链表
void ListPrint(LTNode* phead)
{//循环链表,从head的下一个节点开始打印assert(phead);//链表不能为空//head是哨兵位节点,是空的,所以不打印LTNode* cur = phead->next;while (cur!=phead){cout << cur->data<<"->";cur = cur->next;}cout << endl;
}
//4.尾插
//已经创建了一个哨兵位头节点,所以尾插不需要传入二级指针
void ListPushBack(LTNode* phead,LTDateType x)
{//断言,链表不为空assert(phead);//创建一个新的节点LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));newnode->data=x;//在新创建的节点中插入数据//LTNode* newnode=BuyListNode(x);LTNode* tail = phead->prev;//定义一个变量指向链表的尾部tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;
}
//5.尾删
void ListPopBack(LTNode* phead)
{//断言,链表不为空assert(phead);//防止删除掉创建的哨兵位节点assert(phead->next != phead);//法1//LTNode* tail = phead->prev;//指向链表的尾节点//tail->prev->next = phead;//phead->next = tail->prev;//free(tail);//法2,多定义几个变量LTNode* tail = phead->prev;//尾节点LTNode* tailPrev = tail->prev;//尾节点的前一个节点free(tail);tailPrev->next = phead;phead->prev = tailPrev;
}
LTNode* BuyListNode(LTDateType x)//用于创建新的节点
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));newnode->data = x;newnode->next = NULL;//滞空newnode->prev = NULL;//滞空return newnode;
}
//6.头插
void ListPushFront(LTNode* phead, LTDateType x)
{//注意插入的位置!//在哨兵位节点和第一个位置之间插入数据assert(phead);//由于每次都要检查扩展一个新的节点,所以设置一个函数专门用于扩展LTNode* newnode = BuyListNode(x);//创建好节点后,开始进行插入操作//找到哨兵位头节点后真正的第一个节点LTNode* next = phead->next;phead->next = newnode;newnode->prev = phead;newnode->next = next;next->prev = newnode;
}
//7.头删
void ListPopFront(ListNode* phead)
{assert(phead);//防止将哨兵位节点删掉assert(phead->next != phead);//定义多个变量,增加程序的可读性LTNode* next = phead->next;//要删除的头部节点LTNode* nextNext = next->next;//头数据的下一个节点phead->next = nextNext;nextNext->prev = phead;//要记得将删除的头部节点的内存还给系统free(next);
}
//8.查找
//根据传进来的数字在链表中查找是否有相同的
LTNode* ListFind(LTNode* phead,LTDateType x)
{assert(phead);//从哨兵位节点的下一个节点开始查找LTNode* cur = phead->next;//限定范围,即何时停止查找while (cur!= phead){if (cur->data == x){return cur;}else{cur = cur->next;}}//未查找到return NULL;
}
//9.pos位置前插入
void ListInsert(LTNode* pos,LTDateType x)//可直接代替头插和尾差,即直接在这两个函数体中调用该函数
{assert(pos);//创建一个新节点LTNode* newnode = BuyListNode(x);//创建一个变量指向pos位置前的一个节点LTNode* posPrev = pos->prev;posPrev->next = newnode;newnode->prev = posPrev;newnode->next = pos;pos->prev = newnode;
}
//10.删除pos位置
void ListErase(LTNode* pos)
{assert(pos);LTNode* posPrev = pos->prev;LTNode* posNext = pos->next;posPrev->next = posNext;posNext->prev = posPrev;free(pos);pos = NULL;
}
//11.销毁链表
void ListDestroy(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;//先释放除哨兵位头结点以外的节点,再单独销毁哨兵位头节点while (cur != phead){LTNode* next = cur->next;//先保存下一个节点的地址,防止被置成随机值后找不到free(cur);cur = next;}free(phead);phead = NULL;//不能使plist清理干净,可在测试类中手动清理
}

每写一个功能,都要进行一次测试,以下为所有的测试类合集:

//测试类
void Test()
{//初始化LTNode* plist = ListInit();//尾插cout << "尾插测试:" << endl;ListPushBack(plist, 1);ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPushBack(plist, 5);ListPrint(plist);cout << "---------------" << endl;//尾删cout << "尾删测试:" << endl;ListPopBack(plist);ListPopBack(plist);ListPrint(plist);cout << "---------------" << endl;cout << "头插测试:" << endl;ListPushFront(plist, 3);ListPushFront(plist,4);ListPushFront(plist, 5);ListPrint(plist);cout << "---------------" << endl;cout << "头删测试:" << endl;ListPopFront(plist);ListPrint(plist);cout << "---------------" << endl;cout << "查找测试:(修改数值)" << endl;LTNode* pos = ListFind(plist,4);//利用查找修改数值if (pos){pos->data = 7;}ListPrint(plist);cout << "---------------" << endl;cout << "在pos位置前插入测试:" << endl;//配合查找,插入数据LTNode* search = ListFind(plist, 1);//即在1的前面插入节点ListInsert(search, 9);ListPrint(plist);cout << "---------------" << endl;cout << "删除pos位置节点测试:" << endl;LTNode* search2 = ListFind(plist, 2);ListErase(search2);ListPrint(plist);cout << "---------------" << endl;//销毁链表ListDestroy(plist);plist = NULL;ListPrint(plist);
}
int main()
{Test();return 0;
}

以下为运行测试类时的最终结果:(因最终链表销毁,故无法进行打印,assert自动截止)

三.顺序表&链表

CPU

L1cache

L2cache                 寄存器                                      分别遍历顺序表和链表

L3cache

(假设顺序表的地址为0x00123400)访问储存位置时,先看这个地址在不在缓冲区中,在就直接访问,不再就先加载到缓存,再访问。假设不命中,依次加载20byte到缓存(具体加载多大取决于硬件体系)

顺序表是连续的,故CPU高速缓存命中率高

链表是非连续的,每个节点都由一个指针,故CPU高速缓存命中率更低

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147997.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

面试官:Spring是如何解决循依赖问题?

Spring 的循环依赖一直都是 Spring 中一个很重要的话题&#xff0c;一方面是 Spring 为了解决循环依赖做了很多工作&#xff0c;另一个方面是因为它是面试 Spring 的常客&#xff0c;因为他要求你看过 Spring 的源码&#xff0c;如果没有看过 Spring 源码你基本上是回答不了这个…

【Java】线程暂停比拼:wait() 和 sleep()的较量

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持&#xff01; 在Java多线程编程中&#xff0c;合理地控制线程的执行是至关重要的。wait()和sleep()是两个常用的方法&#xff0c;它们都可以用来暂停线程的执行&#xff0c;但它们之间存在着显著的差异。本文将详…

移动技术开发:RecyclerView瀑布流水果列表

1 实验名称 RecyclerView瀑布流水果列表 2 实验目的 掌握RecyclerView控件的实现方法和基本应用 3 实验源代码 布局文件代码&#xff1a; activity_main&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android&q…

Mac系统Docker中SQLserver数据库文件恢复记录

Mac系统Docker中SQLserver数据库文件恢复记录 Mac想要安装SQLsever&#xff0c;通过docker去拉去镜像是最简单方法。 一、下载Docker Docker 下载安装&#xff1a; 需要‘科学上网’ 才能访问到docker官网。&#xff08; https://docs.docker.com/desktop/install/mac-ins…

18.2K Star,AI 高效视频监控摄像头

Hi&#xff0c;骚年&#xff0c;我是大 G&#xff0c;公众号「GitHub 指北」会推荐 GitHub 上有趣有用的项目&#xff0c;一分钟 get 一个优秀的开源项目&#xff0c;挖掘开源的价值&#xff0c;欢迎关注。 导语 在家庭和企业安防领域&#xff0c;实时视频监控是保障安全的核…

2024 SNERT 预备队招新 CTF 体验赛-Web

目录 1、robots 2、NOF12 3、get_post 4、好事慢磨 5、uploads 6、rce 7、ezsql 8、RCE 1、robots robots 协议又叫爬虫协议&#xff0c;访问 robots.txt 继续访问 /JAY.php 拿到 flag&#xff1a;flag{hello_Do_YOU_KONw_JAY!} 2、NOF12 F12 和右键都被禁用 方法&#…

22、Raven2

难度 中 目标 root权限 4个flag 使用Virtualbox启动 kali 192.168.86.105 靶机 192.168.86.106 信息收集 看到111端口有一个rpc相关的东西&#xff0c;去网上查看了一下是什么服务 通过在网上搜索发现这是一个信息泄露的漏洞&#xff0c;上面的这个端口其实就是泄露的端口和…

【Spring 底层原理】手搓一个Spring框架

文章目录 准备工作Spring 框架到底在干啥&#xff1f;几个概念辨析注解的定义自定义核心注解配置类启动类辅助类 Spring 容器XxxAware 回调机制初始化机制前置、后置处理器完整的容器代码源码下载 最近工作接触到的知识比较底层&#xff0c;因此为了突破瓶颈&#xff0c;彻底搞…

ubuntu+MobaXterm+ssh+运行Qt(成功版)

点击上方"蓝字"关注我们 01、ubuntu连接SSH >>> 通过串口工具连接ubuntu 登录 解决连接不上的问题 检查 SSH 服务:确保目标机器上 SSH 服务已启动。你可以在目标机器上运行以下命令: sudo systemctl status ssh 如果没有运行,可以使用以下命令启动 SSH …

英特尔AI加速器Gaudi 3下周发布,挑战NVIDIA统治地位!

英特尔正稳步推进其2024年计划&#xff0c;备受瞩目的AI加速器Gaudi3预计将于下周震撼登场。这款被誉为英特尔AI英雄的产品&#xff0c;专注于处理大规模训练和推理任务&#xff0c;拥有无与伦比的扩展能力。面对市场对高效能半导体的旺盛需求&#xff0c;英特尔首席执行官帕特…

FX5 CPU模块和以太网模块的以太网通信功能

FX5 CPU模块和以太网模块的以太网通信功能的概要如下所示。 CPU模块的内置以太网端口的通信规格如下所示。 1、与MELSOFT的直接连接 不使用集线器&#xff0c;用1根以太网电缆直接连接以太网搭载模块与工程工具(GX Torks3)。无需设定IP地址&#xff0c;仅连接目标指定即可进行…

无服务器计算构建人工智能管理区块链系统

图片发自简书App 图片发自简书App 本发明属于网络版权管理技术领域&#xff0c;特别涉及一种以交易信息作 为唯一标准发行虚拟币的区块链系统。 背景技术 数字代币如比特币、以太坊等是区块链技术的实现方式之一&#xff0c;目 标是取代法定货币流通&#xff0c;通过“挖矿”的…

前端-js例子:收钱转账

支付宝转账 在这里用到周期定时器setInterval(function,time)&#xff0c;设置达到目标钱数时停止定时器。 点击转账按钮时&#xff0c;开始函数显示。 同时要确定输入框里输入的是数字。&#xff08;有一定容错&#xff09; window.onloadfunction(){var btn document.que…

什么是慢充优惠话费充值api?如何选择平台

一、话费充值api的定义 话费充值api是一种能够让开发者将话费充值功能集成到自己的平台的接口。通过接入话费充值api接口&#xff0c;就能够实现话费充值平台的搭建&#xff0c;从而为用户提供话费充值服务&#xff0c;这一接口主要适用于对话费充值有长期稳定需求的企业或者商…

K8s容器运行时,移除Dockershim后存在哪些疑惑?

K8s容器运行时&#xff0c;移除Dockershim后存在哪些疑惑&#xff1f; 大家好&#xff0c;我是秋意零。 K8s版本截止目前&#xff08;24/09&#xff09;已经发布到了1.31.x版本。早在K8s版本从1.24.x起&#xff08;22/05&#xff09;&#xff0c;默认的容器运行时就不再是Doc…

排序-----归并排序(递归版)

核心思想&#xff1a;假设数组前后两部分各自有序&#xff0c;然后各定义两个指针&#xff0c;谁小谁放到新开辟的数组里面&#xff0c;最后把新开辟的数组赋值给原数组就完成了。要使前后两部分有序就采用递归的方式&#xff0c;不断往下划分块&#xff0c;最后一层划分为两个…

01 基础request

目录 类 WxRequest 的定义 静态属性 default 构造函数 constructor 方法 request HTTP 方法封装 创建 WxRequest 实例并导出 完整代码&#xff1a; 类 WxRequest 的定义 创建一个 WxRequest 类包含一个静态属性 default 和几个方法&#xff0c;用于处理网络请求。 静态…

【后端开发】JavaEE初阶—Theard类及常见方法—线程的操作(超详解)

前言&#xff1a; &#x1f31f;&#x1f31f;本期讲解多线程的知识哟~~~&#xff0c;希望能帮到屏幕前的你。 &#x1f308;上期博客在这里&#xff1a;【后端开发】JavaEE初阶—线程的理解和编程实现-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondl…

计算机毕业设计之:基于深度学习的路面检测系统(源码+部署文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

鸿蒙OpenHarmony【轻量系统内核扩展组件(CPU占用率)】子系统开发

基本概念 CPU&#xff08;中央处理器&#xff0c;Central Processing Unit&#xff09;占用率分为系统CPU占用率和任务CPU占用率。 系统CPU占用率&#xff1a;是指周期时间内系统的CPU占用率&#xff0c;用于表示系统一段时间内的闲忙程度&#xff0c;也表示CPU的负载情况。系…