一篇文章入门单链表+刷题实践【java实现+详细注释】
创始人
2024-01-30 06:12:36

文章目录

  • 节点定义
  • 链表类
    • 获取链表长度
    • 清空链表
    • 添加节点到链表尾部
    • 根据id来删除节点
    • 根据id来查询节点
    • 修改相同id的节点信息
    • 打印链表
    • 逆序打印
    • 反转链表
  • 测试
    • 代码
    • 打印信息
  • 习题
    • 反转链表
    • 删除链表的节点
    • 删除链表的倒数第k个节点

节点定义

关于节点里面所存储的信息,需要什么就添加什么,但是next字段是必须的,因为用来串联一个节点和下一个节点。

package com.dam.data_structure.linked_list;public class HeroNode {/*** 这三个字段自己定义*/public int id;public String name;public String nickname;/*** 必要字段*/public HeroNode next;public HeroNode(int id, String name, String nickname) {this.id = id;this.name = name;this.nickname = nickname;}@Overridepublic String toString() {return "HeroNode [id=" + id + ", name=" + name + ", nickname=" + nickname + "]";}public HeroNode next(int id, String name, String nickname) {next = new HeroNode(id, name, nickname);return next;}}

常规添加节点方法,这样很多小伙伴可能会觉得比较麻烦

HeroSingleLinkedList linkedList = new HeroSingleLinkedList();HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");HeroNode hero3 = new HeroNode(3, "吴用", "智多星");HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");linkedList.add(hero1);linkedList.add(hero4);linkedList.add(hero2);linkedList.add(hero3);

这里提供一个快速添加节点的方法

 public HeroNode next(int id, String name, String nickname) {next = new HeroNode(id, name, nickname);return next;}

使用方式

HeroSingleLinkedList linkedList = new HeroSingleLinkedList();链式添加元素linkedList.head.next(5, "小明", "小明").next(6, "小花", "小花").next(7, "小华", "小华").next(8, "李华", "李华");

链表类

本文的链表会使用一个空的结点来作为head,该节点上面没有什么实际数据,只是为了让链表的其他方法更加容易实现

public class HeroSingleLinkedList {/*** 先初始化一个头节点, 头节点不要动, 不存放具体的数据*/private HeroNode head = new HeroNode(0, "", "");
}

获取链表长度

注意,计算长度是从head的下一个节点开始计算

    /*** 获取链表长度** @return*/public int size() {int size = 0;HeroNode temp = this.head.next;while (temp != null) {size++;temp = temp.next;}return size;}

清空链表

直接重置头节点就行

  /*** 清空链表*/public void clear() {this.head.next = null;}

添加节点到链表尾部

找到链表的最后一个节点,将最后一个节点的next指向要添加的节点即可

  /*** 添加元素** @param heroNode*/public void add(HeroNode heroNode) {HeroNode temp = this.head;找到最后一个元素,将heroNode添加即可,最后一个元素的next肯定为nullwhile (temp != null) {if (temp.next == null) {//--if--找到了最后一个元素 添加元素之后即可退出temp.next = heroNode;break;} else {//--if--不是最后一个元素,继续往下面寻找temp = temp.next;}}}

根据id来删除节点

删除节点一般是遍历到要删除节点的前一个元素,然后将前一个元素的next指向null或者要删除元素的下一个节点

   /*** 根据id来删除节点** @param id*/public HeroNode deleteById(int id) {HeroNode temp = this.head;while (temp != null && temp.next != null) {if (temp.next.id == id) {//记录要删除的元素HeroNode record = temp.next;if (temp.next.next != null) {//--if--如果还有下下个节点temp.next = temp.next.next;} else {//--if--如果没有下下节点,直接赋值为空就行temp.next = null;}return record;}temp = temp.next;}System.out.println("没有找到相应id的元素,无需删除");return null;}

根据id来查询节点

   /*** 根据id来查询节点** @param id*/public HeroNode getById(int id) {HeroNode temp = this.head;while (temp != null) {if (temp.id == id) {return temp;}temp = temp.next;}System.out.println("没有找到相应id的元素");return null;}

修改相同id的节点信息

    /*** 根据id匹配来修改节点** @param heroNode*/public void update(HeroNode heroNode) {HeroNode temp = this.head;while (temp != null) {if (temp.id == heroNode.id) {temp.name = heroNode.name;temp.nickname = heroNode.nickname;return;}temp = temp.next;}System.out.println("没有找到相应id的元素,无法修改");}

打印链表

   /*** 打印链表的元素*/public void print() {//不打印头节点,从头节点的后一个元素开始HeroNode temp = this.head.next;while (temp != null) {System.out.println(temp.toString());temp = temp.next;}}

逆序打印

利用栈先进后出特性来协助

  /*** 逆序打印*/public void reversePrint() {//先将所有元素存储到栈中Stack stack = new Stack<>();HeroNode temp = this.head.next;while (temp != null) {stack.push(temp);temp = temp.next;}//从栈中取出元素并打印while (!stack.isEmpty()) {System.out.println(stack.pop().toString());}}

反转链表

反转链表原理
在这里插入图片描述

 /*** 原地反转链表** @param linkedList*/public static void reverseList(HeroSingleLinkedList linkedList) {HeroNode head = linkedList.head;//如果只有一个元素或者没有元素,直接退出即可if (head == null || head.next == null) {return;}HeroNode cur = head.next;HeroNode last = null;while (cur != null) {HeroNode temp = cur.next;cur.next = last;last = cur;cur = temp;}head.next = last;}

测试

代码

package com.dam.data_structure.linked_list;import java.util.Stack;public class HeroSingleLinkedList {/*** 先初始化一个头节点, 头节点不要动, 不存放具体的数据*/private HeroNode head = new HeroNode(0, "", "");/*** 添加元素** @param heroNode*/public void add(HeroNode heroNode) {HeroNode temp = this.head;找到最后一个元素,将heroNode添加即可,最后一个元素的next肯定为nullwhile (temp != null) {if (temp.next == null) {//--if--找到了最后一个元素 添加元素之后即可退出temp.next = heroNode;break;} else {//--if--不是最后一个元素,继续往下面寻找temp = temp.next;}}}/*** 根据id来删除节点** @param id*/public HeroNode deleteById(int id) {HeroNode temp = this.head;while (temp != null && temp.next != null) {if (temp.next.id == id) {//记录要删除的元素HeroNode record = temp.next;if (temp.next.next != null) {//--if--如果还有下下个节点temp.next = temp.next.next;} else {//--if--如果没有下下节点,直接赋值为空就行temp.next = null;}return record;}temp = temp.next;}System.out.println("没有找到相应id的元素,无需删除");return null;}/*** 根据id来查询节点** @param id*/public HeroNode getById(int id) {HeroNode temp = this.head;while (temp != null) {if (temp.id == id) {return temp;}temp = temp.next;}System.out.println("没有找到相应id的元素");return null;}/*** 根据id匹配来修改节点** @param heroNode*/public void update(HeroNode heroNode) {HeroNode temp = this.head;while (temp != null) {if (temp.id == heroNode.id) {temp.name = heroNode.name;temp.nickname = heroNode.nickname;return;}temp = temp.next;}System.out.println("没有找到相应id的元素,无法修改");}/*** 获取链表长度** @return*/public int size() {int size = 0;HeroNode temp = this.head.next;while (temp != null) {size++;temp = temp.next;}return size;}/*** 清空链表*/public void clear() {this.head.next = null;}/*** 打印链表的元素*/public void print() {//不打印头节点,从头节点的后一个元素开始HeroNode temp = this.head.next;while (temp != null) {System.out.println(temp.toString());temp = temp.next;}}/*** 逆序打印*/public void reversePrint() {//先将所有元素存储到栈中Stack stack = new Stack<>();HeroNode temp = this.head.next;while (temp != null) {stack.push(temp);temp = temp.next;}//从栈中取出元素并打印while (!stack.isEmpty()) {System.out.println(stack.pop().toString());}}/*** 原地反转链表** @param linkedList*/public static void reverseList(HeroSingleLinkedList linkedList) {HeroNode head = linkedList.head;//如果只有一个元素或者没有元素,直接退出即可if (head == null || head.next == null) {return;}HeroNode cur = head.next;HeroNode last = null;while (cur != null) {HeroNode temp = cur.next;cur.next = last;last = cur;cur = temp;}head.next = last;}public static void main(String[] args) {HeroSingleLinkedList linkedList = new HeroSingleLinkedList();链式添加元素linkedList.head.next(5, "小明", "小明").next(6, "小花", "小花").next(7, "小华", "小华").next(8, "李华", "李华");插入测试HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");HeroNode hero3 = new HeroNode(3, "吴用", "智多星");HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");linkedList.add(hero1);linkedList.add(hero4);linkedList.add(hero2);linkedList.add(hero3);正序打印测试System.out.println("正序打印测试---------------------------------------------------------------------------------------");linkedList.print();System.out.println();逆序打印测试System.out.println("逆序打印测试---------------------------------------------------------------------------------------");linkedList.reversePrint();System.out.println();获取链表长度测试System.out.println("获取链表长度测试---------------------------------------------------------------------------------------");System.out.println("链表长度:" + linkedList.size());System.out.println();反转链表System.out.println("反转链表测试---------------------------------------------------------------------------------------");HeroSingleLinkedList.reverseList(linkedList);linkedList.print();System.out.println();修改元素System.out.println("修改链表元素测试---------------------------------------------------------------------------------------");linkedList.update(new HeroNode(4, "武松", "行者"));linkedList.print();System.out.println();根据id查询元素System.out.println("根据id查询元素---------------------------------------------------------------------------------------");System.out.println("linkedList.getById(2):" + linkedList.getById(2));System.out.println();删除元素System.out.println("删除链表元素测试---------------------------------------------------------------------------------------");linkedList.print();System.out.println("删除10");linkedList.deleteById(10);System.out.println("删除1");linkedList.deleteById(1);linkedList.print();System.out.println("删除3");linkedList.deleteById(3);linkedList.print();System.out.println("删除4");linkedList.deleteById(4);linkedList.print();System.out.println("删除2");linkedList.deleteById(2);linkedList.print();System.out.println();}
}

打印信息

正序打印测试---------------------------------------------------------------------------------------
HeroNode [id=5, name=小明, nickname=小明]
HeroNode [id=6, name=小花, nickname=小花]
HeroNode [id=7, name=小华, nickname=小华]
HeroNode [id=8, name=李华, nickname=李华]
HeroNode [id=1, name=宋江, nickname=及时雨]
HeroNode [id=4, name=林冲, nickname=豹子头]
HeroNode [id=2, name=卢俊义, nickname=玉麒麟]
HeroNode [id=3, name=吴用, nickname=智多星]逆序打印测试---------------------------------------------------------------------------------------
HeroNode [id=3, name=吴用, nickname=智多星]
HeroNode [id=2, name=卢俊义, nickname=玉麒麟]
HeroNode [id=4, name=林冲, nickname=豹子头]
HeroNode [id=1, name=宋江, nickname=及时雨]
HeroNode [id=8, name=李华, nickname=李华]
HeroNode [id=7, name=小华, nickname=小华]
HeroNode [id=6, name=小花, nickname=小花]
HeroNode [id=5, name=小明, nickname=小明]获取链表长度测试---------------------------------------------------------------------------------------
链表长度:8反转链表测试---------------------------------------------------------------------------------------
HeroNode [id=3, name=吴用, nickname=智多星]
HeroNode [id=2, name=卢俊义, nickname=玉麒麟]
HeroNode [id=4, name=林冲, nickname=豹子头]
HeroNode [id=1, name=宋江, nickname=及时雨]
HeroNode [id=8, name=李华, nickname=李华]
HeroNode [id=7, name=小华, nickname=小华]
HeroNode [id=6, name=小花, nickname=小花]
HeroNode [id=5, name=小明, nickname=小明]修改链表元素测试---------------------------------------------------------------------------------------
HeroNode [id=3, name=吴用, nickname=智多星]
HeroNode [id=2, name=卢俊义, nickname=玉麒麟]
HeroNode [id=4, name=武松, nickname=行者]
HeroNode [id=1, name=宋江, nickname=及时雨]
HeroNode [id=8, name=李华, nickname=李华]
HeroNode [id=7, name=小华, nickname=小华]
HeroNode [id=6, name=小花, nickname=小花]
HeroNode [id=5, name=小明, nickname=小明]根据id查询元素---------------------------------------------------------------------------------------
linkedList.getById(2):HeroNode [id=2, name=卢俊义, nickname=玉麒麟]删除链表元素测试---------------------------------------------------------------------------------------
HeroNode [id=3, name=吴用, nickname=智多星]
HeroNode [id=2, name=卢俊义, nickname=玉麒麟]
HeroNode [id=4, name=武松, nickname=行者]
HeroNode [id=1, name=宋江, nickname=及时雨]
HeroNode [id=8, name=李华, nickname=李华]
HeroNode [id=7, name=小华, nickname=小华]
HeroNode [id=6, name=小花, nickname=小花]
HeroNode [id=5, name=小明, nickname=小明]
删除10
没有找到相应id的元素,无需删除
删除1
HeroNode [id=3, name=吴用, nickname=智多星]
HeroNode [id=2, name=卢俊义, nickname=玉麒麟]
HeroNode [id=4, name=武松, nickname=行者]
HeroNode [id=8, name=李华, nickname=李华]
HeroNode [id=7, name=小华, nickname=小华]
HeroNode [id=6, name=小花, nickname=小花]
HeroNode [id=5, name=小明, nickname=小明]
删除3
HeroNode [id=2, name=卢俊义, nickname=玉麒麟]
HeroNode [id=4, name=武松, nickname=行者]
HeroNode [id=8, name=李华, nickname=李华]
HeroNode [id=7, name=小华, nickname=小华]
HeroNode [id=6, name=小花, nickname=小花]
HeroNode [id=5, name=小明, nickname=小明]
删除4
HeroNode [id=2, name=卢俊义, nickname=玉麒麟]
HeroNode [id=8, name=李华, nickname=李华]
HeroNode [id=7, name=小华, nickname=小华]
HeroNode [id=6, name=小花, nickname=小花]
HeroNode [id=5, name=小明, nickname=小明]
删除2
HeroNode [id=8, name=李华, nickname=李华]
HeroNode [id=7, name=小华, nickname=小华]
HeroNode [id=6, name=小花, nickname=小花]
HeroNode [id=5, name=小明, nickname=小明]Process finished with exit code 0

习题

反转链表

https://leetcode.cn/problems/fan-zhuan-lian-biao-lcof/

/*** 注意:head上面也有值,不是单纯作为头节点* @param head* @return*/
public ListNode reverseList(ListNode head) {ListNode cur = head;ListNode last = null;while (cur != null) {//先将cur后面的部分存储起来ListNode temp = cur.next;cur.next = last;last = cur;cur = temp;}return last;
}

删除链表的节点

https://leetcode.cn/problems/shan-chu-lian-biao-de-jie-dian-lcof/

public ListNode deleteNode(ListNode head, int val) {if (head == null) {return null;}if (head.val == val) {//删除头节点,直接返回头节点的下一个节点即可return head.next;}ListNode temp = head;while (temp != null && temp.next != null) {if (temp.next.val == val) {if (temp.next.next != null) {temp.next = temp.next.next;} else {temp.next = null;}break;}temp = temp.next;}return head;
}

删除链表的倒数第k个节点

https://leetcode.cn/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/

public ListNode getKthFromEnd(ListNode head, int k) {ListNode fast = head;ListNode slow = head;//让快指针先走k步for (int i = 0; i < k; i++) {fast = fast.next;}//快慢一起走,快走到尽头,慢就是倒数第k个while (true) {if (fast == null) {break;}fast = fast.next;slow = slow.next;}return slow;
}

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
最安全的匿名举报方式 匿名12... 来源:中安在线8月9日,河北邢台小伙张钊(化名)在河北政务服务网12345平台举报楼上邻居涉嫌非法开...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
中国光棍有多少人 2020年9... 我国是世界上人口最多的国家,庞大的人口基数为我国的发展带来了许多的益处。但是同时,我国也是出生人口性...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...