数据结构:LinkedList与链表

数据结构:LinkedList与链表

1:链表的概念及结构:

逻辑上连续,物理上不一定连续

重点掌握

2:创建MySingleList类

再定义一个内部类ListNode,整形val为节点的值域,ListNode型的next为下一个节点的地址,再给出一个带参数的构造方法用于初始化val。再定义head为链表的头结点,size为链表的长度。

3:createList方法:创建链表

用new关键字实例化5个节点并分别赋值,然后用next指针连接起来,并将node1设置为头节点。

效果图:

4:addFirst方法:在链表头部插入元素

先实例化node对象,并赋值为data。

再判断头结点是否为空,如果为空将node赋值给head。

如果不是将node的next指针设为head,再将node赋给head。

5:addLast方法:在链表尾部插入元素:

new关键字实例化node对象,并赋值为data。

判断head是否为空,如果为空直接把node赋给head,结束程序。

创建一个cur对象并其赋值为head。

用while循环遍历到链表最后一个元素,此时设cur的next指针为node。

6:add方法:任意位置插入元素

先判断下标是否小于0或大于链表长度,如果是就结束程序。

如果下标为0,调用头插法;如果下标为链表长度,调用尾插法。

都不是创建node对象,赋值为data,调用subNode1方法找到pos位置的前一个元素sub,把sub的next指针赋给node的next指针,实现插入的操作(改线),最后让sub的next指针指向node。

效果图:

输出结果:

7:find方法:查找是否包含关键字key在链表中

创建一个cur对象,将head赋值给它。

用while循环遍历链表,如果某个cur的val值等于key,返回true。如果遍历完也没找到,返回false。

8:remove方法:删除第一次出现关键字为key的节点

创建一个cur节点,并将head赋值给它。

然后用while循环遍历链表,如果某个cur的val值等于key,则通过subNode2方法找到key的前一个结点sub,让sub的next指针指向原本cur指向的next指针,也就是cur的下一个元素,相当于改线间接跳过了cur,达到了删除cur的效果。

9:subNode2方法:找到数值为data的元素的前一个元素

创建cur对象,并将head赋值给它。

用while循环遍历链表,如果cur的下一个元素的值等于data,返回cur,如果没有就返回null。

10:removeAllKey方法:删除所有值为key的结点(面试题1)

创建对象cur和node1,将head赋值它们。

创建对象node2,将head的下一个元素赋值给它。

如果头结点的val值等于key,将head向后移一个,删除第一个头结点。

然后用while循环遍历链表,如果node2的val值等于key,让node1的next指针指向node2的下一个元素,不再指向node2,然后node2向后移一个,原来的node2位置的元素就被删除了。

如果node2的val值不等于key,就将node1赋值给node2,让两者处于同一个结点上,node2往后移一个,直到遍历完链表

11:display方法:遍历链表

定义cur对象,并把head赋值给它。

然后用while循环遍历链表,打印每个节点的val值,同时计算链表的长度。

12 :size方法:计算链表的长度

用while循环遍历链表,然后size++

输出结果:

13:clear方法:清空链表

将头结点置为空。

14:reverseList方法:反转一个单链表(面试题2)

(1)如果链表为空,直接返回空。

(2)如果链表的头结点的next为空,直接返回head。

(3)将头结点的next指针赋给cur,再将头结点的next指针置为空,达到反转的效果。

(4)while循环遍历链表,创建curNext用于保存的cur的next指针,然后将cur的next指针指向头结点,再移动头结点到cur位置上,cur再移动到下一个节点,直到完成逆转。

效果图:

输出结果:

15:middleNode方法:返回链表的中间节点(面试题3)

创建两个节点fast和slow,都赋值为head。

然后用while循环,让fast速度是slow的两倍,遍历整个链表,最后slow所在的节点就是中间节点。

效果图:

输出结果:

16:findKthToTail方法:返回该链表中倒数第K个结点 (面试题4)

此题的核心思想:让fast先走k-1步,再让fast和slow同步走,最终返回倒数第k个结点。

效果图:

输出结果:

17:mergeTwoLists方法:拼接两个链表 (面试题5)

(1)创建两个节点newHead和tmpHead,并没有实际含义的结点。

(2)然后while循环遍历链表,headA和headB都不为空,如果headA的val大于headB,tmpHead的next指针指向headB,然后headB向后移动一个长度。反之同理。

(3)最后判断完以后,tmpHead往后移动一个节点。

(1):链表B遍历完了,剩下的结点就放到链表A里面。

(2):链表A遍历完了,剩下的结点就放到链表B里面。

(3):最后返回newHead的next指针,就是两个链表的中头结点val值更小的那个结点。

示意图:

在main方法中运行:

输出结果:

18:partition方法:以定值x为基准把链表分成两部分,小于x的结点排在前,大于x的结点排在后。(面试题6)

将链表分为两部分,前半部分的头和尾分别为bs和be,后半部分的头和尾分别为as和ae,将head赋值给cur。

然后用while循环遍历链表:

(1)如果cur的val值比x小,判断bs是否为空,如果为空就cur赋值给bs和be,如果不是就把cur赋给be的next指针,be再往后移一个。

(2)如果cur的val值比x大,as和ae的操作与bs和be同理。

让前半部分的尾部be的next指针指向后半部分的头部as。

为了防止最大的元素不是最后一个,要将ae的next指针置为空。

再将bs赋给cur1,用while循环遍历分隔后的链表。

效果图:

输出结果:

19:chkPalindrome方法:判断链表是否回文(面试题7)

(1)要先找到链表的中间节点,然后反转链表,与前面提到过的方法一致,最后比较val值,如果不一样就返回false,全部一样就返回true。

输出结果:

20:getIntersectionNode方法:输入两个链表,找到它们的第一个公共节点 。(面试题8)

首先普及一个误区,不是数值一样就是公共节点,而是像第2条链表的第二个结点一样,其next指针指向第一个链表的结点,实现相交,呈现Y字形

效果图:

(1)分别设定链表A和链表B的长度为lenA和lenB。

(2)设pl指向的是最长的链表的头结点,ps指向的是最短的链表的头结点。

(3)然后用while循环遍历链表,分别求出lenA和lenB的长度。

(4)再次将headA和headB分别赋给pl和ps。

(1)求出lenA和lenB的长度差len,如果差值小于0,则说明A的长度小于B,将headB赋给pl,将headA赋给ps,用lenB减去lenA,确保len是正数。

(2)用while循环,让pl遍历完比ps长的那一部分。

(3)再用while循环,分别让pl和ps遍历链表,直到相遇,返回pl。

(4)创建一个方法相交链表,为的是能在idea上实现代码的运行。

效果图:

在main方法中运行:

输出结果:

21: hasCycle方法:判断链表是否有环(面试题9)

(1)先判断头结点是否为空,为空直接返回false。

(2)再定义两个节点fast和slow,同时赋值给head,然后用while循环遍历链表,fast走的速度是slow的两倍,如果fast和slpw相遇了返回true,遍历完了没相遇返回false。

效果图:

输出结果:

22:detectCycle方法:返回链表入环的第一个节点,如果链表无环则返回null(面试题10 )

(1)如果头结点为空,直接返回空。

(2)然后定义两个节点fast和slow,同时赋值为head。

(3)然后用while循环遍历链表,fast的速度是slow的2倍,如果fast和slow相遇了就结束循环。

如果fast或者fast的next指针为空,则说明链表无环,直接返回空。

然后再次把头结点赋给fast,再通过while循环,让fast和slow一步一步走,直到相遇,最后返回相遇结点。

createLoop方法:创建一个环。

通过while循环,遍历到链表最后一个结点,让这个结点的next指针指向头结点的next,也就是链表的第二个结点,形成一个环。

效果图:

在main方法中调用:

输出结果:

1:无头双向链表

效果图:

2:创建MyLinkedList链表

创建内部类ListNode,定义数值val, ListNode类型的prev和next指针,同时给出一个构造方法实例化数值val,然后定义head和last结点和size长度。

3:addFirst方法(在链表头部插入元素)

如果头结点为空,将node赋给head和last。

绕过node的next指针指向头结点,再让head的prev的指针指向node,最后把node赋给head。

示意图:

4:addLast尾插法:插入尾部元素

如果头结点为空,把node赋给head和last。

让last的next指针指向node,让node的prev指针指向last,把node赋给node。

示意图:

5:addIndex方法:任意位置插入

(1)先判断下标index是否违规,如果是则直接结束程序。

(2)然后找到下标为index的元素cur,实例化数值为data的结点node。

(3)再让node的next指向cur,再让node的前一个结点的next指针指向node,再让node的prev指针指向cur的前一个元素,最后让cur的prev的指针指向node。

searchIndex方法:通过while循环找到下标为index的元素。

示意图:

6:contain方法:查找链表中是否包含某元素

用while循环遍历链表,如果某个cur.val等于key,直接返回true。

7: size方法:求链表的长度

用while循环遍历链表,同时size++,最后返回size。

8:clear方法:清空链表

通过while循环,将每个结点的prev和next指针、head和last都置为空。

在main方法中调用:

输出结果:

​​​​​​​

9:remove方法:删除第一次出现的关键字key

思路图:

思路分析:

在main方法中调用:

输出结果:

10:removeAllKey方法:删除所有的关键字的key

大体思路:与remove方法差不多,但是删除key以后还要继续遍历链表

思路分析:

在main方法中运行:

输出结果:

11:ArrayList与LinkedList的区别:

ArrayList的核心是数组,LinkedList的核心是改线。

相关推荐
Yang-Never5 分钟前
Open GL ES ->GLSurfaceView在正交投影下的图片旋转、缩放、位移
android·开发语言·kotlin·android studio·贴图
程序员清风9 分钟前
Redis Pipeline 和 MGET,如果报错了,他们的异常机制是什么样的?
java·后端·面试
风铃儿~15 分钟前
Sentinel深度解析:微服务流量防卫兵的原理与实践
java·微服务·sentinel
niuniu_66625 分钟前
针对 Python 3.7.0,以下是 Selenium 版本的兼容性建议和安装步骤
开发语言·chrome·python·selenium·测试工具
zyx没烦恼25 分钟前
Linux 下 日志系统搭建全攻略
linux·服务器·开发语言·c++
苏卫苏卫苏卫28 分钟前
【Python】数据结构练习
开发语言·数据结构·笔记·python·numpy·pandas
审计侠35 分钟前
Go语言-初学者日记(四):包管理
开发语言·后端·golang
辰辰大美女呀1 小时前
C 语言高级编程指南:回调函数与设计模式
c语言·开发语言·设计模式
青云交1 小时前
Java 大视界 -- Java 大数据机器学习模型在金融衍生品定价中的创新方法与实践(166)
java·大数据·金融·数据采集·机器学习模型·java 大数据·金融衍生品定价
yanyu-yaya1 小时前
第三章 react redux的学习之redux和react-redux,@reduxjs/toolkit依赖结合使用
javascript·学习·react.js