算法通关村第一关——链表青铜挑战笔记

434 阅读4分钟

如何使用Java构建链表以及链表各个位置的插入与删除

Java如何构造链表(单向链表)

首先需要我们理解链表的含义

链表之所以叫链表,就因为它相当于一条铁链,一环扣着一环;链表中包含多个节点,每个节点都包含了两个部分,一个部分记录的是当前节点的value值,而另一个部分则是指向下一个节点的指针next;

注意:链表包含多种结构,单向链表,双向链表,单向循环链表,双向循环链表;此处重点关注单向链表

链表的结构:

image.png

其中N1节通常记作head;

Java语言是怎么构造链表这一数据结构的呢?

C语言是通过结构体来定义链表结构的,而Java语言则是通过定义Java对象来构造链表结构的;

为了体现出Java语言面向对象的特点------封装性;ListNode类的定义如下;

public class ListNode{
    private int val; // 当前节点的值
    private ListNode next; // 下一个节点的指针
    public ListNode(int val){
        this.val=val;
    }
    
    public void setNext(ListNode nextNode){
        this.next=nextNode;
    }
    public void setVal(int val){
        this.val=val;
    }
    
    public ListNode getNext(){
        return next;
    }
    public int getVal(){
        return val;
    }
    
    // 构建一个链表
    public static void main(String[] args){
        ListNode head=new ListNode(10);
        ListNode node01=new ListNode(12);
        ListNode node02=new ListNode(15);
        ListNode node03=new ListNode(20);
        head.setNext(node01);
        node01.setNext(node02);
        node02.setNext(node03);
    }
    
}

此时一个链表已经构造完成。如下图所示; image.png 但一般为了方便在刷题过程中的使用,比如leetcode,ListNode类的定义就比较简单了

public class ListNode{
    int val;
    ListNode next;
    public ListNode(int val){
        this.val=val;
    }
     public static void main(String[] args){
        ListNode head=new ListNode(10);
        ListNode node01=new ListNode(12);
        ListNode node02=new ListNode(15);
        ListNode node03=new ListNode(20);
        head.next=node01;
        node01.next=node02;
        node02.next=node03;  // 链表构建完成
    }
}

使用这种方式构建链表是为了更加方便做题者解题过程中对链表的操作;直接使用head.next就可以定位到下一个节点,而不是head.getNext();通过方法去得到下一个节点;

如何使用Java语言来遍历链表

//给定一个链表结构 10 --> 12 --> 15 --> 20 -->null
public void printNode(ListNode head){
    int len=0;
    while(head!=null){
        len++;
        System.out.println(head.val);
        head=head.next;
    }
     System.out.println(len); //得到链表的总长度;
}

链表的插入

1.头插法

当前需要插入的节点为newNode;首先需要将插入节点的下一个指针指向原来的头节点head; 即 newNode.next=head; 然后需要将新插入的节点作为新的头节点 head=newNode;(这一步不能忘记)

//给定一个链表结构 10 --> 12 --> 15 --> 20 -->null,在头部插入新节点100
 public static ListNode addFromHead(ListNode head,ListNode newNode){
        newNode.next=head;
        head=newNode;
        return head;
}

结果如下:

image.<img src="png" alt="" width="70%" />

2.在链表中插入

当前需要插入的节点为newNode,以及当前插入节点的前一个节点为curNode; 首先需要将当前插入节点的下一个指针指向curNode节点的下一个;即 newNode.next=curNode.next; 然后将curNode的下一个指向插入节点newNode; 即curNode.next=newNode;

//给定一个链表结构 10 --> 12 --> 15 --> 20 -->null,在节点 15 之后插入新节点 100
public void addNodeFromMiddle(ListNode head,ListNode curNode,ListNode newNode){
    ListNode temp=head;
    // 先找到在链表中需要插入节点的位置
    while(temp!=null){
        if(temp==curNode){
            // 链表中插入节点
            newNode.next=curNode.next;
            curNode.next=newNode;
            break;
        }
        temp=temp.next;
    }
}

结果如下: image.png

3.尾插法

当前需要插入的元素为newNode,插入的位置为链表结尾处curNode;让newNode的下一个指针指向null;即newNode.next=null;

让curNode的下一个指针指向newNode; 即curNode.next=newNode;

public void addNodeFromTail(ListNode head,ListNode newNode){
    ListNode temp=head;
    while(temp.next!=null){
        temp=temp.next;
    }
 //   newNode.next=null; (newNode.next本来就为null)
    temp.next=newNode;
}

结果如下:

image.png

链表中的节点的删除

1.删除表头结点

Java中删除头部节点的过程比较简单,让当前头节点来到头节点下一个的位置;即head=head.next;即可

// 给定链表 10-->12-->15-->20-->null
public ListNode delHead(ListNode head){
    head=head.next;
    return head;
}

image.png

2.删除链表中间节点

一般删除中间节点都是给定中间节点的value值,在遍历链表的过程中先找到被删除节点的位置,然后再删除;

假设被删除节点已经被找到为delNode,前驱节点为curNode; 那么删除节点的操作为 先将当前节点的下一个指向被删除节点的下一个;即 curNode.next=delNode.next;然后再将被删除节点的下一个指向null;即 delNode.next=null;

// 给定链表 10-->12-->15-->20-->null   删除值为15的节点
public static void delMiddleNode(ListNode head,int value){
    ListNode temp=head;
    while(temp.next!=null){
        if(temp.next.val==value){
            ListNode cur=temp;
            ListNode delNode=temp.next;
            cur.next=delNode.next;
            delNode.next=null;
            break;
        }
        temp=temp.next;
    }
}

结果如下

image.png

3.删除尾部节点

给定一个链表,先要删除尾部节点;首先需要定位到尾部节点的前驱节点curNode,直接让curNode.next指向null即可;

怎么定位到curNode呢? 可以定义快慢指针,快指针先走一步,慢指针才开始走;这样当快指针来到待删除尾部节点时,刚好慢指针也来到新的尾部节点位置curNode;

// 给定链表 10-->12-->15-->20-->null  删除尾部节点
public static void delTailNode(ListNode head){
    ListNode temp1=head.next; // 快指针
    ListNode temp2=head; // 慢指针
    while(temp1!=null){
        if(temp1.next==null){
            temp2.next=null;
        }
        temp1=temp1.next;
        temp2=temp2.next;
    }
}

结果如图:

image.png

以上就是个人对Java中构建链表,以及链表的插入与删除操作的理解;