当前位置: 首页 > 编程日记 > 正文

带哨兵节点的链_【算法导论】10.2不带哨兵节点和带哨兵节点的双向链表

不带哨兵节点的双向链表即一般的双向链表,有一个头指针指向第一个节点,每个节点有key值和两个指针next和pre,分别指向前后相邻的节点,头结点的pre=NULL,尾节点的next=NULL,比较明了,但是也有麻烦的地方:在做查找删除节点等操作的时候,免不了要判断边界条件,比如node==NULL等。先来看看这种链表的代码:

/*

* 实现没有哨兵节点的双向链表,需要自己判断边界条件

*/

#include

using namespace std;

class list {

struct node {

int key;

node* next;

node* pre;

node(int k) :

key(k), next(NULL), pre(NULL) {

}

};

public:

node* head;

int len;

list() :

head(NULL), len(0) {

}

~list() {

node* tmp1 = head, *tmp2;

while (tmp1 != NULL) {

tmp2 = tmp1->next;

delete tmp1;

len--;

cout << "len=" << len << endl;

tmp1 = tmp2;

}

}

/*

* 在头处插入节点

*/

void insertHead(int k) {

node* n = new node(k);

n->next = head;

head = n;

if (n->next != NULL) {

n->next->pre = n;

}

len++;

}

/*

* 删除指针指向的节点

*/

int del(node* n) {

if (n == NULL) {

return -1;

}

if (n->pre != NULL) {

n->pre->next = n->next;

} else {

head = n->next;

}

if (n->next != NULL) {

n->next->pre = n->pre;

}

delete n;

len--;

return n->key;

}

/*

* 查找具有某个key值的节点

*/

node* searchList(int k) {

if (len == 0) {

return NULL;

}

node* tmp = head;

while (tmp != NULL) {

if (tmp->key == k) {

break;

}

tmp = tmp->next;

}

return tmp;

}

/*

* 遍历list

*/

void travelList() {

node* tmp = head;

while (tmp != NULL) {

cout << tmp->key << ' ';

tmp = tmp->next;

}

cout << endl;

}

};

int main() {

list* l = new list();

l->insertHead(5);

l->insertHead(4);

l->insertHead(3);

l->travelList();

l->del(l->head->next);

l->travelList();

delete l;

return 0;

}

每次判断边界条件,虽然不会从根本上增加时间复杂度,但是对其常数项还是有影响的;而如果使用带哨兵节点构成的双向循环链表,则可以省去这些问题。我们使用一个“哑的”NIL节点来代替之前的head头指针,NIL节点的key值没有实际的意义,主要关注它的next和pre,初始的时候,链表只有一个NIL节点,NIL.next指向自己,NIL.pre也指向自己。当添加了若干个节点之后,NIL.next指向头节点,而NIL.pre则指向尾节点;而同样的,这时头节点的pre不再是NULL而是指向NIL,尾节点的next也不再是NULL,也是指向NIL。

这样的好处在于,我们判断边界条件的时候,不需要再判断是否为空,尤其在删除节点的时候,只需要写两句即可。但是这样也带来一些问题,就是要额外分配空间来存储NIL节点,如果对于多个比较短的链表而言,这样可能会代码比较大的冗余空间。

代码如下:

/*

* 实现带哨兵是双向循环链表

*/

#include

using namespace std;

class list {

struct node {

int key;

node* next;

node* pre;

node(int k) :

key(k), next(NULL), pre(NULL) {

}

};

//node* head;

public:

node* nil; //哨兵节点

int len;

list() :

nil(), len(0) {

nil = new node(0); //初始化哨兵节点

//让链表循环起来

nil->next = nil;

nil->pre = nil;

}

~list() {

//析构的时候要delete掉还存在于list中的节点

if (len == 0) {

delete nil;

return;

}

node* n1 = nil->next;

node* n2 = NULL;

while (n1 != NULL && n1 != nil) {

n2 = n1->next;

delete n1;

len--;

n1 = n2;

}

delete nil;

}

/*

* 在头部插入节点

*/

void insertHead(int k) {

node* n = new node(k);

n->next = nil->next;

n->pre = nil;

nil->next = n;

//这一句不要丢了

n->next->pre = n;

len++;

}

/*

* 删除节点,这里删除的操作只需要写两句,比不带哨兵的链表操作要简洁的多

*/

void del(node* n) {

n->pre->next = n->next;

n->next->pre = n->pre;

delete n;

len--;

}

node* searchList(int k) {

node* tmp = nil->next;

//让nil的key值永远不可能等于k

//nil->key = k + 1;

//while (tmp->key != k) {

while (tmp != nil && tmp->key != k) {

tmp = tmp->next;

}

if (tmp != nil) {

return tmp;

} else {

return NULL;

}

}

/*

* 从next指针方向遍历链表

*/

void travelClockwise() {

node* tmp = nil->next;

while (tmp != nil) {

cout << tmp->key << ' ';

tmp = tmp->next;

}

cout << endl;

}

/*

* 从pre指针方向遍历链表

*/

void travelAnticlockwise() {

node* tmp = nil->pre;

while (tmp != nil) {

cout << tmp->key << ' ';

tmp = tmp->pre;

}

cout << endl;

}

};

int main() {

list* l = new list();

l->insertHead(5);

l->insertHead(4);

l->insertHead(3);

l->travelClockwise();

l->del(l->nil->pre);

//l->travelClockwise();

l->travelAnticlockwise();

return 0;

}

相关文章:

Android环境结构--安装Eclipse错

在学习安卓第一步。成立了一个开发环境。经验&#xff0c;知道&#xff0c;所以这一步是不容易&#xff0c;因为你觉得&#xff0c;我可能是太幸运了。我见到 题。 首先&#xff0c;安装Eclipse的时候。 【Problem 1】 【问题原因】&#xff1a; &#xff08;1&#xff09; 安装…

ThinkPHP的标签制作

thinkphp的默认标签解析器在Lib/Template/TagLib/TagLibCx.class中里面定义了常用的volist php 等常用thinkphp的标签这里笔者在这个类中添加一个<category>的标签解析标签格式&#xff1a;<category parentid0 ><{$cat.catname}></category>标签作用&…

Go进阶:反射3定律

各位学习Go语言的朋友&#xff0c;周末好&#xff0c;这次跟大家聊一聊Go语言的一个高级话题&#xff1a;反射。 这篇文章是从我过去的学习笔记修改来的&#xff0c;内容主要来自Go Blog的一篇文章《The law of reflection》。 这篇文章主要介绍反射和接口的关系&#xff0c;解…

qlabel可以选中吗_Qt QLabel详解

Qt QLabel详解Qt QLabel详解一、QLabel常用方法1. QLabel设置文本内容ui.label->setText(QStringLiteral("测试中文\n"));2. QLabel设置颜色通过设计器里面的改变样式进行设置&#xff1a;同时可以设置字体、文本对齐方式、背景图片color: rgb(255, 85, 0);backgr…

数据库种类 以及优缺点

1.MySQL MySQL是最受欢迎的开源SQL数据库管理系统&#xff0c;它由 MySQL AB开发、发布和支持。MySQL AB是一家基于MySQL开发人员的商业公司&#xff0c;它是一家使用了一种成功的商业模式来结合开源价值和方法论的第二代开源公司。MySQL是MySQL AB的注册商标。 MySQL是一个快速…

xcode 4.2 不再支持 Window-Based Application 的解决办法(转载)

xcode 4.2 不再支持 Window-Based Application 的解决办法&#xff1a; 1.创建空项目 Empty Application。&#xff08;在Xcode4.2下创建的这个空项目不再有MainWindow.xib文件了。&#xff09; 2.CtrlN&#xff0c;创建User Interface下面的Window&#xff08;选择“i…

java知识概论

转载于:https://www.cnblogs.com/arrows/p/10432301.html

及cp含义_当我们谈论CP时,我们在谈论什么?

2015年B站UP主剪刀手轩辕投稿了一个名为《【魔性拉郎群像】你问我爱你有多深》的视频&#xff0c;让伏黛(伏地魔林黛玉)这个CP走进了众多二次元观众的视野&#xff0c;让这个超级冷门的小众CP一跃成为微博超话&#xff0c;甚至还上了当时的微博热搜。其实早在2010年&#xff0c…

40个出色的Wordpress cms插件

WordPress is a great blogging platform with a potential of being an easy to use content management system. This is the third article of our three-part series, “The Comprehensive Guide for a Powerful CMS using WordPress”. We are taking a look at 40 qualit…

Xcode 添加代码块

我们经常会定义一些retain的property&#xff0c;而且大概每次我们都会像这样写&#xff1a; property (nonatomic, retain) Type *name; 每次都要老老实实的把“property (nonatomic, retain)”敲一遍&#xff0c;这样太累了。 那么能不能像XCode自带的代码提示功能一样&…

软考自查:计算机网络

计算机网络 内容提要 七层模型网络技术标准与协议网络类型与拓扑结构网络规划与设计IP地址与子网划分特殊含义IP地址HTML无线网网络接入技术IPv6OSI/RM七层模型 七层模型练习题 某IP网络连接如图所示&#xff0c;在这种配置下IP全局广播分组不能够通过的路径是_B_。A&#xff1…

restful url 设计规范_restFul接口设计规范

1. 域名应该尽量将API部署在专用域名之下。https://api.example.com如果确定API很简单&#xff0c;不会有进一步扩展&#xff0c;可以考虑放在主域名下。https://example.org/api/2. 版本(Versioning)应该将API的版本号放入URL。http://www.example.com/app/1.0/foohttp://www.…

Dictionary作为数据源绑定,调用c++库中返回为BYTE*的函数,listView项排序

最近在做一个电子档案管理的项目。现在还处于初期&#xff0c;只是做一个简单demo拿去跟客户演示。至于最后谈不谈得下来&#xff0c;到底做不做&#xff0c;反正我是不看好&#xff0c;但没因为这样就马马虎虎、草草了事。这个项目算是b/s加c/s混合体&#xff0c;现在已经做的…

ES6 新特性

ES6 先阅读这个http://gejiawen.github.io/2015/07/28/Javascript/ECMAScript6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E7%B3%BB%E5%88%97/ECMAScript6%E6%96%B0%E7%89%B9%E6%80%A7%E7%AE%80%E4%BB%8B/ ES6的特性在chrome中默认是关闭的 Visit chrome://flags/#enable-javascrip…

一次被僵尸网络病毒攻击的过程

事件背景 回想起来应该算是去年的事情了, 时值 2019 年 1 月 24 日早上, 当时我正忙碌于开发手头的一个珠宝分销系统项目, 由于已经进行了多日封闭式开发, 项目初见效果, 准备放到内网服务器 A 上跑跑看. 项目的一些功能需要通过公网才能访问, 于是便打算通过一台之前就架设在公…

c2 链路_POS链路不能打开的解决办法

介绍的是POS链路不能打开的解决办法&#xff0c;其原因是C2字节不匹配&#xff0c;这里以华为路由器为组网环境。一、网络环境路由器A有GE接口和2.5G POS接口与其他路由器连接&#xff0c;启动路由器A后&#xff0c;发现GE端口的状态为正常开启&#xff0c;但2.5G POS端口无法开…

“寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面

如果第二次看到我的文章&#xff0c;欢迎下方扫码订阅我的个人公众号&#xff08;跨界架构师&#xff09;哟~本文长度为5723字&#xff0c;建议阅读15分钟。坚持原创&#xff0c;每一篇都是用心之作&#xff5e;这是一篇以程序员视角写的文章&#xff0c;但是内容是互联网行业通…

TCP拥塞控制算法内核实现剖析(二)

内核版本&#xff1a;2.6.37 主要源文件&#xff1a;linux-2.6.37/ net/ ipv4/ tcp_bic.c 本文主要分析BIC算法实现 1. 相关结构体和参数 /* BIC TCP Parameters */struct bictcp {u32 cnt ; /* increase cwnd by 1 after ACKs */u32 last_max_cwnd ; /* last maximum snd_cw…

关于IOS中的self关键字

在C#、Java中都有一个关键字this用于表示当前对象&#xff0c;其实在ObjC中也有一个类似的关键字self&#xff0c;只是self不仅可以表示当前对象还可以表示类本身&#xff0c;也就是说它既可以用在静态方法中又可以用在动态方法中。-(void)setName:(NSString *)name andAge:(in…

中值定理符号怎么读_微分、微分中值定理、泰勒公式

问对问题&#xff0c;找对方法&#xff0c;做对的事~ 黑莓 2020/10/09 温习001-031逻辑、集合、空间 线性代数00线性代数研究什么内容&#xff1f;-上海交大032-047行列式的定义、性质与计算10/03048-078矩阵的定义、运算10/03079-117可逆矩阵、初等变换与秩10/04…

Java高级特性增强-多线程

请戳GitHub原文: https://github.com/wangzhiwub... 大数据成神之路系列&#xff1a; 请戳GitHub原文: https://github.com/wangzhiwub... Java高级特性增强-集合 Java高级特性增强-多线程 Java高级特性增强-Synchronized Java高级特性增强-volatile Java高级特性增强-并发集合…

微软企业库4.1学习笔记(八)创建对象 续集2

3.3通过配置指定和Unity的整合 另外一种方法是在配置源中指定配置的需要&#xff0c;你可以指定下面的一条或者多条&#xff1a; 你可以在Unity配置中指定想要的BlockExtensions  你可以在Unity配置中的type配置节指定如何创建企业库对象&#xff0c;指定类型映射的关系&…

Kali Linux python 安装pip

安装pip&#xff1a;apt-get install python-setuptoolseasy_install pippip install xxxx转载于:https://www.cnblogs.com/arhatlohan/p/4737828.html

3dmax图像采样器抗锯齿_内幕揭秘!同样的场景同一张图,用3DMAX网渲平台进行二次渲染时间竟然相差3个小时之多!...

一个分辨率:4000*2000的室内客餐厅&#xff0c;3dmax版本是2014版本&#xff0c;渲染器版本为vray3.63&#xff0c;机器&#xff1a;阿里云1台服务器&#xff0c;这个同样的场景同样的参数同一张图&#xff0c;用3dmax网渲平台进行二次渲染发现时间相差了将近3个小时之多&#…

2015/8/18

一、git, switch to找不到师傅新创的branch 解决方法&#xff1a;切到git视图去pull&#xff0c;然后切回java视图&#xff0c;再Team->switch to&#xff0c;就能找到了 二、在师傅的环境中能successful&#xff0c;在我的环境中却是failed 解决方法&#xff1a;eclipse-&g…

Javascript - prototype、__proto__、constructor

最近看了很多文章&#xff0c;想要更通透的搞懂JS中的prototype、__proto__与constructor属性&#xff0c;从各个博主的文章里摘取了我认为可以有助于理解的一些内容&#xff0c;希望自己能够掌握好这一重要知识点的同时也帮助到大家&#xff0c;具体内容请见下文。 &#xff0…

DOS下读取4GB内存

好文章我收集下起来 CPU上电后&#xff0c;从ROM 中的BIOS开始运行。 BIOS是处在内存的最顶端64KB&#xff08;FFFF0000H&#xff09;&#xff0c;还是1MB之下的64KB&#xff08;F0000H&#xff09;处呢&#xff1f;事实上&#xff0c;BIOS在这两个地方都同时出现。 在保护模式…

7纳米duv和euv_要超车台积电 三星宣布采用EUV技术7纳米制程完成验证

在晶圆代工市场&#xff0c;台积电与三星的竞争始终是大家关心的戏码。三星虽然有高通等VIP客户&#xff0c;但在7纳米制程节点&#xff0c;高通预计会转投台积电&#xff0c;三星要想受更多客户的青睐&#xff0c;只能从制程技术着手了。这也是三星跳过非EUV技术的7纳米制程&a…

HDU 1711 Number Sequence(KMP算法)

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1711 Number Sequence Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 15548 Accepted Submission(s): 6836Problem DescriptionGiven two s…

分享45款高质量的免费(X)HTML/CSS模板

当你需要在短时间内设计出一个网站的时候&#xff0c;网站模板就非常有用了。这也就是为什么这些设计模板已成为设计领域的最新趋势的原因。在这篇文章中&#xff0c;收集了各式各样的网站模板&#xff0c;您可以免费下载使用&#xff0c;希望这些设计模板不仅带给您灵感&#…