链表的基本操作

本文详细介绍了链表的基础操作,包括单向和双向链表、带傀儡节点与不带傀儡节点的区别。重点讲解了链表的遍历方法,如不带傀儡节点和带傀儡节点的链表遍历。接着阐述了如何在链表中插入元素,如插入头部、中部和尾部,并提供了相应的代码实现。对于链表元素的删除,文章提到了按值、位置以及节点下标删除的方法,还包括了一种特殊的‘移花接木’删除技巧。
摘要由CSDN通过智能技术生成

链表的基本操作

链表的分类

  1. 单向/双向(引入了 prev 引用)
  2. 带傀儡节点/不带傀儡节点(dummy node)
  3. 带环/不带环

链表的遍历

遍历方式可利用 while 或者 for 循环来进行实现,主要代码块可展示为:

//for循环实现
for(Node cur = head; cur != null; cur = cur.next){
    ....
}
//while循环实现
Node cur = head;
while(cur != null){
    ....
    cur = cur.next;
}

1.遍历 不带傀儡节点的链表

//遍历 不带傀儡节点的链表
    public static void print(Node head){
        for(Node cur = head; cur != null; cur= cur.next){
            System.out.println(cur.val);
        }
    }

2.遍历 带傀儡节点的链表

//遍历 带傀儡节点的链表
    public static void printWithDummy(Node head){
        for(Node cur = head.next; cur != null; cur = cur.next){
            System.out.println(cur.val);
        }
    }

链表元素的插入

  • 元素插入链表头部

  • 元素插入链表中部

  • 元素插入链表尾部

    1.插入头部位置和中间位置
    在这里插入图片描述
    2.插入尾部位置

一般情况下尾部插入一个节点的相关代码如下:

//尾插一个节点
    public static void insertTail(Node head,int val){
        if(head == null){
            return;
        }
        // 1)找到末尾节点
        Node prev = head;
        while(prev != null){
            prev = prev.next;
        }
        //循环结束的时候,cur 就是最后一个节点
        Node newNode = new Node(val);
        newNode.next = prev.next;
        prev.next = newNode;
    }

当链表本身为空链表时,要实现插入元素,就需要借助 方法的返回值/成员变量 来实现,相关代码如下:

//insertTail方法
public static Node insertTail(Node head,int val){
    Node newNode = new Node(val);
    if(head == null){
       return newNode;
    }
    Node prev = head;
    while(prev.next != null){
        prev = prev.next;
    }
    newNode.next = prev.next;
    prev.next = newNode;
    return head;
}

//main函数
public static void main(String[] args) {
Node head = null;
head = insertTail(head,val:100);
print(head);
}

链表元素的删除

  • 删除一般节点
  • 删除头节点(需更改 head 的指向)
    1.删除一般节点一般有三种方法:一种是按 待删除节点的值 进行删除;一种是按 待删除节点的位置 进行删除;一种是按 节点下标 进行删除
   //删除节点-按值删除
    public static void remove1(Node head,int value){
        // 1)找 val 对应的位置,同时找到 val 前一个位置
        Node prev = head;
        while(prev != null
                && prev.next != null
                && prev.next.val != value){
            prev = prev.next;
        }
        // 2)循环结束,prev 指向待删除的前一个节点
        if(prev == null || prev.next == null){
            //未找到值为 val 的节点
            return;
        }
        // 3)删除这个节点 toDelete 指向待删除节点
        Node toDelete = prev.next;
        prev.next = toDelete.next;
    }

    //删除节点-按位置删除
    public static void remove2(Node head,Node toDelete){
        // 1.找到 toDelete 前一个节点
        Node prev = head;
        while(prev != null && prev.next != toDelete){
            prev = prev.next;
        }
        if(prev == null){
            //没找到
            return;
        }
        // 2.进行删除
        prev.next = toDelete.next;
    }
    
     //按照 节点下标 进行删除
    public static int size(Node head){
        int size = 0;
        for(Node cur = head; cur != null; cur = cur.next){
            size++;
        }
        return size;
    }
    public static void remove3(Node head,int index){
        if(index < 0 || index >= size(head)){
            return;
        }
        if(index == 0){
            //TODO
        }
        // 1.找到待删除节点前一个的位置:即 index-1
        Node prev = head;
        for(int i = 0;i < index -1; i++){
            prev = prev.next;
        }
        //循环结束之后,prev 指向待删除节点的前一个位置
        // 2.进行删除操作
        Node toDelete = prev.next;
        prev.next = toDelete.next;
    }

2.“移花接木”删除节点
不涉及链表的遍历,直接将待删除节点之后的节点复制到待删除节点处
缺点:无法删除最后一个节点

  //“移花接木”删除节点
    public static void remove4(Node head,Node toDelete){
        Node nextNode = toDelete.next;
        toDelete.val = nextNode.val;
        toDelete.next = nextNode.next;
    }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值