重新认识链表(下)

栏目: 数据库 · 发布时间: 6年前

内容简介:写链表代码是最考验有些语言有“指针”的概念,比如 C 语言;有些语言没有指针,取而代之的是“引用”,比如 Java、Python。不管是“指针”还是“引用”,实际上,它们的意思都是一样的,都是存储所指对象的内存地址。将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针,或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量。

写链表代码是最考验 逻辑思维能力 的,指针来回指,指着指着就指迷糊,在写代码之前先注意这么几个问题。

问题1:什么是指针?

定义:

有些语言有“指针”的概念,比如 C 语言;有些语言没有指针,取而代之的是“引用”,比如 Java 、Python。不管是“指针”还是“引用”,实际上,它们的意思都是一样的,都是存储所指对象的内存地址。

将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针,或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量。

举例:

最常见的指针代码应该是这个了, p->next=q 。它的意思是说p 结点中的 next 指针存储了 q 结点的内存地址。

问题2:什么是指针丢失和内存泄漏?

在插入结点时,一定要注意操作的顺序。

因为操作不当的时候,很容易造成指针丢失。比如a ->b之间插入一个c,同时不注意的时候很容易这么写

//声明一个p;

p->next = c; // 将 p 的 next 指针指向 c 结点; 

c->next = p->next; // 将 c 的结点的 next 指针指向 b 结点;

这就很容易让链表断成两半,造成指针丢失。正确的写法是将二三两行代码顺序换过来即可。

删除链表结点时,也一定要记得手动释放内存空间。

和插入一样,如果不及时释放内存空间,积少成多,很容易造成内存泄漏。

技巧:利用哨兵节点简化实现难度

哨兵节点主要是处理边界问题的,并不直接参与业务逻辑,当引入哨兵节点的时候,不管链表是不是空,head 指针都会一直指向这个哨兵结点。我们也把这种有哨兵结点的链表叫 带头链表 。相反,没有哨兵结点的链表就叫作 不带头链表

练习:

以单链表为例,所有源码均已上传至github: github.com/chaoaiqi/st…

声明一个单链表类

重新认识链表(下)

1.实现单链表、循环链表、双向链表,支持增删操作

顺序插入

重新认识链表(下)

删除,难点就一行q.next = q.next.next;

重新认识链表(下)

查询,分两个,一个是根据下标查询,一个是根据value查询

重新认识链表(下) 重新认识链表(下)

测试结果:

重新认识链表(下)

2.单链表反转

该实现的思想是: 从前往后反转各个结点的指针域的指向

将当前节点cur的next节点 缓存到nextNode,然后更改当前节点指针指向上一结点prevNode。也就是说在反转当前结点指针指向前,先把当前结点的指针域用nextNode临时保存,以便下一次使用

重新认识链表(下) .

测试结果:

重新认识链表(下)

3.链表中环的检测

该检测的核心思想是: 快慢指针法 。在这里,满指针每走一步,快指针走两步,可以用 数学归纳法 来考虑,首先,如果链表是个环,所以相遇的过程可以看作是快指针从后边追赶慢指针的过程。那么

1:快指针与慢指针之间差一步。此时继续往后走,慢指针前进一步,快指针前进两步,两者相遇。

2:快指针与慢指针之间差两步。此时继续往后走,慢指针前进一步,快指针前进两步,两者之间相差一步,转化为第一种情况。

...

N:快指针与慢指针之间差N步。此时继续往后走,慢指针前进一步,快指针前进两步,两者之间相差(N+1-2)-> N-1步。

代码如下:

重新认识链表(下)

测试结果:

重新认识链表(下)

4.求链表的中间结点

该实现也是用到了 快慢指针法

代码如下:

重新认识链表(下)

测试结果如下:

重新认识链表(下)

5.删除链表倒数第 n 个结点

该实现依旧用到了快慢指针法,不过和之前的有一点区别。以node长度为n,删倒数第k(k<n)个为例。首先,第一个while先计算如果正着删,需要让慢指针走几步,计算为n-k。第二个while循环则通过遍历快指针计算定位需要走n-k步,得到preNode。然后判断是否为空,不为空则常规方法删除。

测试结果

重新认识链表(下)

还有种思路是通过递归来进行删除,本次不做阐述。

6.两个有序的链表合并

该实现的思路是,首先比较两个有序链表,如果pNode为空,直接返回qNode,反之qNode为空,则返回pNode,然后比较p和q,将最小的节点赋值给resNode,同时将最小的节点向后移动一位。设置一个node指向resNode节点,用于方便连接其它节点,在继续比较p和q,同样选出小的那个节点,将该节点设为合并后的链表的第二个节点,用node.next表示该节点,一直重复上述过程,直到p和q有一个为null,然后再将不为null的节点放入新链表后即可。

重新认识链表(下)

测试结果:

重新认识链表(下)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

设计之下

设计之下

搜狐新闻客户端UED团队 / 电子工业出版社 / 2014-1-1 / CNY 69.00

形而上者谓之道,形而下者谓之器。匠者,器也。处身平凡的匠人不断追求向上的设计之道。本书没有华丽的辞藻和长篇大论的理论,作者是搜狐一线的设计团队,写作过程中他们尽力还原真实的工作场景,并总结出了一些实用的经验和方法。 《设计之下》共三部分,全面讲解了用户体验设计的流程和方法。第一部分为“交互设计”,阐述了从项目启动、解析需求到原型设计的过程,并且总结了交互设计的要点:大局观、操作流程简捷、形式......一起来看看 《设计之下》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具