关于节点里面所存储的信息,需要什么就添加什么,但是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;
}
@Override
public 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肯定为null
while (temp != null) {
if (temp.next == null) {
//--if--找到了最后一个元素 添加元素之后即可退出
temp.next = heroNode;
break;
} else {
//--if--不是最后一个元素,继续往下面寻找
temp = temp.next;
}
}
}
删除节点一般是遍历到要删除节点的前一个元素,然后将前一个元素的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来查询节点
*
* @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的元素,无法修改");
}
/**
* 打印链表的元素
*/
public void print() {
//不打印头节点,从头节点的后一个元素开始
HeroNode temp = this.head.next;
while (temp != null) {
System.out.println(temp.toString());
temp = temp.next;
}
}
利用栈先进后出特性来协助
/**
* 逆序打印
*/
public void reversePrint() {
//先将所有元素存储到栈中
Stack<HeroNode> 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肯定为null
while (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<HeroNode> 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;
}
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;
}
https://leetcode.cn/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof/description/
/**
* 借助辅助节点
*
* @param l1
* @param l2
* @return
*/
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//添加一个辅助节点,主要是方便后面的连接操作
ListNode merge = new ListNode(-1);
ListNode temp = merge;
//当l1和l2都不为空的时候,就需要判断哪个更小
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
temp.next = l1;
l1 = l1.next;
} else {
temp.next = l2;
l2 = l2.next;
}
temp = temp.next;
}
//当有一个为空之后,后面的值直接和不为空的那个链表片段一样就行
temp.next = l1 != null ? l1 : l2;
//注意返回的是辅助节点.next
return merge.next;
}