数据结构 | 单链表的增删改查详解(不带头节点)

单链表: 是一种链式存取的数据结构,用一组任意地址空间(即存储单元)来存放线性表的数据元素。单链表中的每个数据都以节点的形式来表示,每个节点都是由值域及指针next域构成,其中值域保存当前节点的数据值,next域保存下个节点的地址。

单链表的结构如下所示:(以不带头节点为例)
在这里插入图片描述
链表“增删改查”的原理(附代码):
(1)头插: 将新节点newEntry的next域链接到头节点的地址中,同时更新头节点
在这里插入图片描述

  • 代码如下:
public void addHead(E value) {
        Entry<E> newEntry = new Entry<>(value);
        if (headEntry == null) {
            headEntry = newEntry;
            tailEntry = newEntry;
        } else {
            newEntry.next=headEntry;
            headEntry = newEntry;//用newEntry更新headEntry,使newEntry变为新的头节点,尾部节点不做改动
        }
    }

(2)尾插: 将尾节点tailEntry的next域链接到新节点的地址中,同时更新尾节点
在这里插入图片描述

  • 代码如下:
public void addTail(E value) {
        Entry<E> newEntry = new Entry<>(value);
        if (headEntry == null) {
            headEntry = newEntry;
            tailEntry = newEntry;
        } else {
            tailEntry.next=newEntry;
            tailEntry = newEntry;
        }
    }

(3)头删: 头节点的value域置空以防止内存泄漏,将其下个节点的地址更新为新的头节点
在这里插入图片描述

  • 代码如下:
public void removeHead() {
        if (headEntry == null) {
            return;
        }
        headEntry.value=null;//防止内存泄漏
        headEntry = headEntry.next;
    }

(4)尾删: 遍历整个链表,标记尾部前驱节点,将前驱节点的next域置空,同时更新尾节点
在这里插入图片描述

  • 代码如下:
public void removeTail() {
        if (headEntry == null) {
            return;
        } else if (headEntry.next== null) {//只有一个节点
            headEntry = null;
            tailEntry = null;
            return;
        } else { //尾删时需要找到尾结点前驱,将前驱节点的next域置空即找实现尾删
            Entry<E> beforeEntry=headEntry;
            for(;beforeEntry.next.next!=null;beforeEntry=beforeEntry.next){
                ;
            }
            tailEntry.value=null;//防止内存泄漏
            beforeEntry.next=null;  //将尾结点置空
            tailEntry=beforeEntry;
        }
    }

(5)删除指定元素: 遍历链表找到与指定元素值相同的元素value,将value前一个节点的next域指向value下一个元素的地址
在这里插入图片描述

  • 代码如下:
public void removeValue(E value) {
        if (headEntry == null) {
            return;
        }
        if (headEntry.value.compareTo(value)==0) {  //指定元素恰为头节点
            removeHead();
        }
        if(tailEntry.value.compareTo(value)==0){    //指定元素恰为尾节点
            removeTail();
        }
        for (Entry<E> p = headEntry; p.next.next!= null; p = p.next) {
            if(p.next.value.compareTo(value)==0){
                p.next.value=null;
                p.next=p.next.next;
                break;
            }
        }
    }

不带头节点的双向单链表结构如下:
在这里插入图片描述
双向单链表的增删改查与上面的原理对应无基本差别,但要分析时记得 更新前驱 pro

  • 代码如下:
public class DuplexLink<E extends Comparable<E>> {
    static class Entry<T extends Comparable<T>>{  //静态内部类
        private T value;
        private Entry<T> next;//后继
        private Entry<T> pro;//前驱
        public Entry(T value){
            this.value=value;
        }
    }
    private Entry<E> headEntry;
    private Entry<E> tailEntry;
    
    //头插
    public void addHead(E value){
        Entry<E> newEntry=new Entry<>(value);
        if(headEntry==null){
            headEntry=newEntry;
            tailEntry=newEntry;
        }//一个节点与普通节点相同
        newEntry.next=headEntry;
        headEntry.pro=newEntry;
        headEntry=newEntry;
    }
    
    //尾插
    public void addTail(E value){
        Entry<E> newEntry=new Entry<>(value);
        if(tailEntry==null){
            headEntry=newEntry;
            tailEntry=newEntry;
        }
        tailEntry.next=newEntry;
        newEntry.pro=tailEntry;
        tailEntry=newEntry;
    }
    
    //头删
    public void removeHead(){
        if (headEntry == null) {
            tailEntry=null;
            return;
        }
        headEntry.next.pro=null;
        headEntry=headEntry.next;
    }
    
    //尾删
    public void removeTail(){
        if (headEntry == null) { //无节点
            return;
        } else if (headEntry.next == null) { //只有一个节点
            headEntry = null;
            tailEntry = null;
            return;
        }else {
            Entry<E> beforeEntry = headEntry;
            for (; beforeEntry.next.next!= null; beforeEntry = beforeEntry.next) {
                ;
            }
            beforeEntry.next = null;
            tailEntry.pro=null;
            tailEntry = beforeEntry;
        }
    }
    
    //删值
    public void removeValue(E value){
        if (headEntry == null) {
            return;
        }
        if (headEntry.value.compareTo(value)==0) {  //若需删除头节点,将其下一个节点置为头节点即可
            headEntry.value=null;
            headEntry=headEntry.next;
            if(headEntry==tailEntry) {
                tailEntry.next=null;
                tailEntry.pro=null;
            }
            return;
        }
        for (Entry<E> p = headEntry; p.next.next!= null; p = p.next) {
            if(p.next.value.compareTo(value)==0){
                p.next.value=null;
                p.next=p.next.next;
                tailEntry.pro=p.pro;
                tailEntry=p;
                break;
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值