前言
学了数据结构之后,就用编程语言去实现它,这样理解才通透。同时地,学会刷题也是很重要,例如现在人尽皆知的leetcode。 我的目标就是进大厂,而必须要过的一关就是数据结构,慢慢学吧~ 行百里者半九十。
我实现数据结构的代码是java,用什么语言不重要,主要是思路正确就可以了。所以你想学习c、c++也是一样的。
然后,这个博客系列是给小白看的,所以我有一些阅读建议:
- 我会给出实现思路,先跟着我一起思考,虽然有些地方说的有些拗口,没办法,这是写作的缺点之一,所以要理解每一个地方说的概念后再往下,不然发现看不懂自然而然就“收藏夹吃灰”了
- 看懂了不一定会,要自己实现一下,你会发现巨多的坑等着你
- 不要急,慢慢来,你可以学会的(真的)
前情回顾:
上一节我们提到了链表,那么我们这一篇就来实现其结构。
链表的定义:
1)链表是以节点的方式来存储是链式存储
2)每个节点包含data域(存放的数据), next域:指向下一个节点,当next指向null时,可以表明才链表元素是尾结点
单向链表
首先,我们设计一个对象Node,对象里面只含有两个字段,分别是data域和next域
并添加上getter、setter方法,这个代码很简单
1 | class Node{ |
接下来,就是设计API了,一个链表,应该拥有插入、删除、打印、获取链表长度等功能
1 | // 传入一个头结点,遍历链表 |
首先,我们来讨论一下主要的API的功能:
插入:
我们要实现的功能是,在i元素之前插入某个新节点。如图:
本来第 i 个节点是直接指向第 i+1 个节点的,由于来了新节点,我们就需要更改一下指向的顺序。
我们要做的具体步骤有三个:
① 找到第i个元素的节点
② 将该节点的next域指向我们传入的新节点
③ 将新节点的next域指向第 i+1 个节点
很简单,是不是?
不过,仔细一看上面这三个步骤,事情并没有那么简单。
我们想一想,如果实现了步骤②,那么到了步骤③,我们如何去表示 i 元素的 next 域呢? 当前状态下, i 元素的 next 域可是新节点噢(步骤②做的事情)。所以我们丢失了原先 i 节点的下一节点,怎么办呢
换个角度想一下,先实现步骤③就可以了。
我们先将新节点指向第 i+1个节点,然后再把 i 节点指向新节点,就可以了(链表当中,顺序很重要)。
删除
而删除的思路跟插入是差不多的,实现的效果是:传入第i个位置的上一个位置,然后删除它下一个节点,再连向下一节点的下一节点。
为什么不直接找到节点然后直接删除呢?因为该链表是单向的,没办法表示“当前节点的上一个节点”,所以我们无法让“上一个节点”与“下一个节点相连”。
所以思路是:从链表头节点一直往下找,找i -1次,就找到了所删除节点的上一节点。
好了,说完思路,我把完整代码贴出来:
1 | class singleLinkedList{ |
环形链表
将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表( circular linked list)。
循环链表如图所示:
跟链表结构没有多大差别,只不过我们判断是否是尾结点的方式由 a.next == null 改成了 a.next == head(头结点)
当next域指向的是头结点时,我们认为当前节点为尾结点。
环形链表的好处:
当我们总是要获取最后一个节点时,可以使用环形链表。
首先实例化一个指向尾结点的变量,这意味着遍历时总是从尾结点开始找,对于前几个元素,只不过把操作数+1;而原本我们想要获取最后一个元素需要操作n次(链表节点个数的大小),而现在,有了环形链表,访问最后一个节点的操作数是1。
但是我们发现,这还是有些不够灵活,如果我们想要获取倒数第二个节点怎么办?
这时候,双向链表就起到了作用……
双向链表
双向链表,就是可以通过两个方向遍历链表,别看这图画的有些复杂,其实就是多了一个pre域(与next域相对的),用于指向上一个节点。
双向链表的优点:
双向链表相对于单链表来说,要更复杂一些,不过,双向链表使得对某个结点的前后结点的操作,带来了方便,可以有效提高算法的时间性能。说白了,就是用空间来换时间。
对于双向链表的操作,也就是多了几步,但原理是一样的。下面举个添加节点的例子表明一下:
步骤①:将node(新节点)的pre域指向temp
步骤②:新节点指向下一节点
步骤③:下一节点的上一节点指向新节点
步骤④:当前节点的下一节点指向node
嗯…好啰嗦好啰嗦,简单来说,就是多了一个pre域,但是指向域的操作顺序是很重要的,不然就发生丢失节点的情况了(参考单向链表)。
添加代码实现:
假设,现在有个新节点node,temp为想要添加位置的前一个位置节点。
1 |
|
写在后面
这个系列会一直写,后面的还有数组、队列、还有我还没学的二叉树等等。
对于知识点梳理的同时,又创作了一篇博客,还有各位小伙伴点的赞,这给我带来无穷大的动力。
冲冲冲!!