链表【java实现】
1. 基础结构介绍
自定义链表类 MyLinkedList, 节点类 ListNode
**
* @author HelloWorld
* @create 2022/9/4 10:17
* @email helloworld.dng@gmail.com
*/
public class MyLinkedList {
/** 链表长度 */
private int size;
/** 虚拟头节点 */
private ListNode head;
/** 尾节点 (真实尾节点,便于实现尾插法)*/
private ListNode tail;
public MyLinkedList() {
this.size = 0;
this.head = new ListNode(0);
}
}
class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
public ListNode(){}
}
2. 链表的创建 - 头插法
public void addAtHead(int val) {
ListNode listNode = new ListNode(val);
listNode.next = head.next;
head.next = listNode;
this.size++;
// 尾指针指向末尾节点
if (size == 1) {
tail = head.next;
}
}
3. 链表的创建 - 尾插法
public void addAtTail(int val) {
if (this.size == 0) {
addAtHead(val);
return;
}
ListNode listNode = new ListNode(val);
tail.next = listNode;
tail = listNode;
this.size++;
}
4. 在任意位置添加新节点
/**
* @description 在链表中的第 index 个节点之前添加值为 val 的节点。
* 如果 index 等于链表的长度,则该节点将附加到链表的末尾。
* 如果 index 大于链表长度,则不会插入节点。
* 如果index小于0,则在头部插入节点。
* @author HelloWorld
* @create 2022/9/4 10:58
* @param index 0 <= index <= size - 1
* @param val
* @return void
*/
public void addAtIndex(int index, int val) {
if (index > size) {
return;
}
if (index <= 0) {
addAtHead(val);
return;
}
if (index == size) {
addAtTail(val);
return;
}
// 中间位置添加节点
ListNode pre = head;
for (int i = 0; i <= index - 1; i++) {
pre = pre.next;
}
ListNode tempNode = new ListNode(val);
tempNode.next = pre.next;
pre.next = tempNode;
this.size++;
}
5. 查询
/**
* @description 获取链表中第 index 个节点的值。如果索引无效,则返回-1; 第一个节点的 index = 0
* @author HelloWorld
* @create 2022/9/4 10:19
* @param index: 0 <= index <= size - 1
* @return int
*/
public int get(int index) {
if (index >= size || index < 0) {
return -1;
}
ListNode now = head;
for (int i = 0; i <= index; i++) {
now = now.next;
}
return now.val;
}
6. 删除任意位置的节点
/**
* @description 如果索引 index 有效,则删除链表中的第 index 个节点。
* @author HelloWorld
* @create 2022/9/4 11:38
* @param index 0 <= index <= size - 1
* @return void
*/
public void deleteAtIndex(int index) {
/* 索引无效 */
if (index < 0 || index >= size) {
return;
}
ListNode pre = head;
for (int i = 0; i < index; i++) {
pre = pre.next;
}
if (index == size - 1) {
tail = pre;
}else {
pre.next = pre.next.next;
}
this.size --;
}
7. 删除链表中重复的节点
/**
* 删除链表中重复的节点 [1, 2, 2, 2, 3, 3, 4] -> [1, 2, 3, 4]
* @param head
* @return
*/
public ListNode deleteDuplicates(ListNode head) {
ListNode now = head;
while (now != null) {
ListNode temp = now.next;
ListNode pre = now;
int currentValue = now.val;
while (temp != null) {
if ((currentValue ^ temp.val) == 0){
pre.next = pre.next.next;
temp = pre.next;
}else {
pre = temp;
temp = temp.next;
}
}
now = now.next;
}
return head;
}
8. 删除有序链表中全部相同的节点
/**
* 有序链表,删除所有val相同的节点 [1, 2, 2, 2, 3, 3, 4] -> [1, 4]
* @param head
* @return
*/
public ListNode deleteDuplicatesOrderList(ListNode head) {
ListNode currentNode = head;
while (nonNull(currentNode.next) && nonNull(currentNode.next.next)) {
ListNode tempNode = currentNode.next;
if (tempNode.val == tempNode.next.val) {
do {
tempNode = tempNode.next;
}while (nonNull(tempNode) && nonNull(tempNode.next) && tempNode.val == tempNode.next.val);
currentNode.next = tempNode.next;
}else {
currentNode = currentNode.next;
}
}
return head;
}
9. 链表反转
/***
* @description 反转链表;[1,2,3,4,5] -> [5,4,3,2,1]
* @author HelloWorld
* @create 2022/9/18 15:58
* @param head
* @return com.wy.leetcode.linkedlist.ListNode
*/
private ListNode reverseList(ListNode head) {
MyLinkedList resultList = new MyLinkedList();
while (nonNull(head.next)) {
head = head.next;
resultList.addAtHead(head.val);
}
return resultList.head;
}
完整代码
package com.wy.leetcode.linkedlist;
import static java.util.Objects.nonNull;
/**
* @author HelloWorld
* @create 2022/9/4 10:17
* @email helloworld.dng@gmail.com
*/
public class MyLinkedList {
/** 链表长度 */
private int size;
/** 虚拟头节点 */
private ListNode head;
/** 尾节点 (真实尾节点,便于实现尾插法)*/
private ListNode tail;
public MyLinkedList() {
this.size = 0;
this.head = new ListNode(0);
}
/**
* @description 获取链表中第 index 个节点的值。如果索引无效,则返回-1; 第一个节点的 index = 0
* @author HelloWorld
* @create 2022/9/4 10:19
* @param index: 0 <= index <= size - 1
* @return int
*/
public int get(int index) {
if (index >= size || index < 0) {
return -1;
}
ListNode now = head;
for (int i = 0; i <= index; i++) {
now = now.next;
}
return now.val;
}
public void addAtHead(int val) {
ListNode listNode = new ListNode(val);
listNode.next = head.next;
head.next = listNode;
this.size++;
// 尾指针指向末尾节点
if (size == 1) {
tail = head.next;
}
}
public void addAtTail(int val) {
if (this.size == 0) {
addAtHead(val);
return;
}
ListNode listNode = new ListNode(val);
tail.next = listNode;
tail = listNode;
this.size++;
}
/**
* @description 在链表中的第 index 个节点之前添加值为 val 的节点。
* 如果 index 等于链表的长度,则该节点将附加到链表的末尾。
* 如果 index 大于链表长度,则不会插入节点。
* 如果index小于0,则在头部插入节点。
* @author HelloWorld
* @create 2022/9/4 10:58
* @param index 0 <= index <= size - 1
* @param val
* @return void
*/
public void addAtIndex(int index, int val) {
if (index > size) {
return;
}
if (index <= 0) {
addAtHead(val);
return;
}
if (index == size) {
addAtTail(val);
return;
}
// 中间位置添加节点
ListNode pre = head;
for (int i = 0; i <= index - 1; i++) {
pre = pre.next;
}
ListNode tempNode = new ListNode(val);
tempNode.next = pre.next;
pre.next = tempNode;
this.size++;
}
/**
* @description 如果索引 index 有效,则删除链表中的第 index 个节点。
* @author HelloWorld
* @create 2022/9/4 11:38
* @param index 0 <= index <= size - 1
* @return void
*/
public void deleteAtIndex(int index) {
/* 索引无效 */
if (index < 0 || index >= size) {
return;
}
ListNode pre = head;
for (int i = 0; i < index; i++) {
pre = pre.next;
}
if (index == size - 1) {
tail = pre;
}else {
pre.next = pre.next.next;
}
this.size --;
}
/**
* 删除链表中重复的节点
* @param head
* @return
*/
public ListNode deleteDuplicates(ListNode head) {
ListNode now = head;
while (now != null) {
ListNode temp = now.next;
ListNode pre = now;
int currentValue = now.val;
while (temp != null) {
if ((currentValue ^ temp.val) == 0){
pre.next = pre.next.next;
temp = pre.next;
}else {
pre = temp;
temp = temp.next;
}
}
now = now.next;
}
return head;
}
/**
* 有序链表,删除所有val相同的节点 [1, 2, 2, 2, 3, 3, 4] -> [1, 4]
* @param head
* @return
*/
public ListNode deleteDuplicatesOrderList(ListNode head) {
ListNode currentNode = head;
while (nonNull(currentNode.next) && nonNull(currentNode.next.next)) {
ListNode tempNode = currentNode.next;
if (tempNode.val == tempNode.next.val) {
do {
tempNode = tempNode.next;
}while (nonNull(tempNode) && nonNull(tempNode.next) && tempNode.val == tempNode.next.val);
currentNode.next = tempNode.next;
}else {
currentNode = currentNode.next;
}
}
return head;
}
/***
* @description 反转链表;[1,2,3,4,5] -> [5,4,3,2,1]
* @author HelloWorld
* @create 2022/9/18 15:58
* @param head
* @return com.wy.leetcode.linkedlist.ListNode
*/
private ListNode reverseList(ListNode head) {
MyLinkedList resultList = new MyLinkedList();
while (nonNull(head.next)) {
head = head.next;
resultList.addAtHead(head.val);
}
return resultList.head;
}
public static void main(String[] args) {
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtTail(1);
myLinkedList.addAtTail(2);
myLinkedList.addAtTail(3);
myLinkedList.addAtTail(4);
myLinkedList.addAtTail(5);
ListNode listNode = myLinkedList.reverseList(myLinkedList.head);
while (listNode.next != null) {
listNode = listNode.next;
System.out.println(listNode.val);
}
}
}
class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
public ListNode(){}
}