目录
2.2.LeetCode中算法题中经常使用这样的方式来创建链表:
从这篇文章开始,正式进入算法学习(纯小白)~
这篇文章是链表的青铜难度学习打卡
一、链表的结构
链表是最基础也是最实用的数据结构之一,常用的链表有单链表和双向循环链表等。
以单链表为例子,节点中一般包含当前节点值以及下一个节点的引用
二、如何创建链表
2.1.一个简单的链表实例,用于演示JVM怎么构造链表的
/**
* 一个简单的链表实例,用于演示JVM怎么构造链表的
*/
public class BasicLink {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5, 6};
Node head = initLinkedList(a);
System.out.println(head);
}
private static Node initLinkedList(int[] array) {
Node head = null, cur = null;
for (int i = 0; i < array.length; i++) {
Node newNode = new Node(array[i]);
newNode.next = null;
if (i == 0) {
head = newNode;
cur = newNode;
} else {
cur.next = newNode;
cur = newNode;
}
}
return head;
}
static class Node {
public int val;
public Node next;
Node(int x) {
val = x;
next = null;
}
}
}
其中val是要存储的值,next是指向下一个结点的引用。
注意打印head
2.2.LeetCode中算法题中经常使用这样的方式来创建链表:
public class ListNode {
//创建链表
public int val;
public ListNode next;
public ListNode(int val){
this.val = val;
this.next = null;
}
}
三、遍历链表
注意不要丢了 head
public static int getListLength(ListNode head){
int len = 0;
ListNode cur = head;
while(cur != null){
len++;
cur = cur.next;
}
return len;
}
这里我先创建了一个链表为135349null
public class MyListNode {
public static ListNode head;
public static ListNode getMyListNode(){
ListNode head = new ListNode(1);
ListNode node2 = new ListNode(3);
ListNode node3 = new ListNode(5);
ListNode node4 = new ListNode(3);
ListNode node5 = new ListNode(4);
ListNode node6 = new ListNode(9);
head.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
return head;
}
public static void main(String[] args) {
MyListNode myLinkedList = new MyListNode();
head = getMyListNode();
printList();
}
遍历
//打印
public static void printList(){
ListNode curr = head;
while(curr != null){
System.out.print(curr.val + " - ");
curr = curr.next;
}
System.out.println("null");
}
四、链表的插入
插入分为 头插、中间插、尾插
4.1.头插
链表表头插入新结点非常简单,容易出错的是经常会忘了head需要重新指向表头。 链表表头插入新结点非常简单,容易出错的是经常会忘了Head需要重新指向表头.
总结就是 head=newNode
上代码
public static void addFirst(int val){
ListNode newHead = new ListNode(val);
newHead.next = head;
head = newHead;
}
4.2.尾插
表尾插入就比较容易了,我们只要将尾结点指向新结点就行了。
上代码
public static void addLast(int val){
ListNode curr = head;
if(head == null){
head = new ListNode(val);
return;
}
while(curr.next != null){
curr = curr.next;
}
curr.next = new ListNode(val);
}
4.3.中间插
在中间位置插入,我们必须先遍历找到要插入的位置,然后将当前位置接入到前驱结点和后继结点之间,但是到了该位置之后我们却不能获得前驱结点了,也就无法将结点接入进来了。
为此,我们要在目标结点的前一个位置停下来,也就是使用cur.next的值而不是cur的值来判断,这是链表最常用的策略。
/**
* 中间插入
*
*/
public static void addMiddle(int index,int val){
ListNode curr = head;
//长度
int size = getLength(getMyListNode());
if(index < 0||index > size){
System.out.println("index不合法!当前size为" + size);
return;
}else if(head == null||index == 0){
addFirst(val);
}else if(index == size){
addLast(val);
}else {
int count = 0;
while(count < index-1){
curr = curr.next;
count++;
}
ListNode newNode = new ListNode(val);
newNode.next = curr.next;
curr.next = newNode;
size++;
}
}
addMiddle(3,888);
综上,我们写出链表插入的方法如下所示:
public static ListNode insertNode(ListNode head, ListNode newNode, int position){
if(head == null){
return newNode;
}
//越界判断
int size = getLength(head);
if(position > size + 1 || position < 1){
System.out.println("位置参数越界");
return head;
}
//表头插入
if(position == 1){
newNode.next = head;
head = newNode;
return head;
}
//表中插入&表尾插入
ListNode cur = head;
int count = 1;
while(count < position - 1){
cur = cur.next;
count++;
}
newNode.next = cur.next;
cur.next = newNode;
return head;
}
五、链表的删除
public static ListNode deleteNode(ListNode head, int position){
if(head == null){
return null;
}
//越界判断
int size = getLength(getMyListNode());
//注意position > size与插入链表节点有所区别
if(position > size || position < 1){
System.out.println("位置参数越界");
return head;
}
//表头删除
if(position == 1){
return head.next;
}
//表中删除&表尾删除
ListNode cur = head;
int count = 1;
while(count < position - 1){
cur = cur.next;
count++;
}
cur.next = cur.next.next;
return head;
}
随机测试两个
打印测试结果,正确!