【数据结构】链表

链表是一种非连续存储的数据结构,由节点组成,每个节点包含数据和指向下一个节点的引用。链表便于插入和删除操作,但查找效率相对较低。本文介绍了链表的创建、单向链表和双向链表节点的定义,以及链表类的方法,如添加、删除、查找等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链表

什么是链表

  • 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
  • 每一个链表都包含多个节点,节点又包含两个部分,一个是数据域(储存节点含有的信息),一个是引用域(储存下一个节点或者上一个节点的地址)。
  • 链表的理解示意图
    在这里插入图片描述

链表的特点是什么

  • 获取数据麻烦,需要遍历查找,比数组慢
  • 方便插入、删除

链表的原理

  • 创建一个节点类,其中节点类包含两个部分,第一个是数据域(你到时候要往节点里面储存的信息),第二个是引用域(相当于指针,单向链表有一个指针,指向下一个节点;双向链表有两个指针,分别指向下一个和上一个节点)
  • 创建一个链表类,其中链表类包含三个属性:头结点、尾节点和大小,方法包含添加、删除、插入等等方法。

单向链表的结点类

public class Node {
    public Object data;
    public Node next;

    public Node(Object e){
        this.data = e;
    }
}

双向链表的节点类

public class Node {
    public Object e;
    public Node next;
    public Node pre;
    public Node(){

    }
    public Node(Object e){
        this.e = e;
        next = null;
        pre = null;
    }
}

链表类

package MutuLink;

public class MyList {
    private Node head;
    private Node tail;
    private int size = 0;

    public MyList() {
        head = new Node();
        tail = new Node();
        head.next =null;
        tail.pre = null;
    }

    public boolean empty() {
        if (head.next == null)
            return true;
        return false;
    }
    //找到所找下标节点的前一个节点
    public Node findpre(int index){
        Node rnode = head;
        int dex = -1;
        while(rnode.next != null){
            //找到了插入节点的上一个节点
            if( dex== index - 1){
                return rnode;
            }
            rnode = rnode.next;
            dex++;
        }
        return null;
    }
    public Node findthis(int index){
        Node rnode = head;
        //把rnode想象为指针,dex为指向的下标,这个地方很容易错,因为当指向最后一个节点时没有判断IF就跳出循环了
        int dex = -1;
        while(rnode.next != null){
            if(dex == index)
            return rnode;
            rnode = rnode.next;
            dex++;
        }
        if(dex == size - 1){
            return rnode;
        }
//        Node test = new Node(new Students("haha",1,2));
        return null;
    }

    // 往链表末尾加入节点
    public void add(Object e) {
        Node node = new Node(e);
        Node rnode = head;
        //如果是空链表的话插入一个节点,这个节点的pre不能指向上一个节点,必须指空
        if (this.empty()) {
            rnode.next = node;
            rnode.next.pre = null;
            tail.pre = node;
            size++;
        } else {
            while (rnode.next != null)
                rnode = rnode.next;
            rnode.next = node;
            node.pre = rnode;
            tail.pre = node;
            size++;
        }
    }
    //往链表的某一个标插入一个节点
    public boolean add(int index,Object e){
        if(index <0||index>=size)
            return false;
        Node node = new Node(e);
        Node prenode = this.findpre(index);
        node.next = prenode.next;
        prenode.next.pre = node;
        prenode.next = node;
        node.pre = prenode;
        size++;
        return true;
    }
    public boolean add(int index,MyList myl){
        if(index <0 || index >= size)
            return false;
        Node prenode = this.findpre(index);
//        myl.tail.pre.next = prenode.next;
//        prenode.pre = myl.tail.pre;
//        tail.pre = null;
//        prenode.next = myl.head.next;
//        myl.head.next.pre = prenode;
//        head.next = null;
        myl.tail.pre.next = prenode.next;
        prenode.next.pre = myl.tail.pre.pre;
        myl.head.next.pre = prenode.pre;
        prenode.next = myl.head.next;
        myl.head = null;
        myl.tail = null;
        size+=myl.size;
        return true;
    }

    public Object remove(int index){
        Object ob= this.get(index);
        if(index <0 || index >= size)
            return null;
        //特殊情况,当移除节点是最后一个节点的时候
        //较为复杂通过画图来写代码
        if(index == size - 1){
            Node prenode = this.findpre(index);
            this.tail.pre = this.tail.pre.pre;
            this.tail.pre.next.pre = null;
            this.tail.pre.next =null;
            size--;
            return ob;
        }
        //比较复杂,通过画图解决
        else{
            Node prenode = this.findpre(index);
            prenode.next = prenode.next.next;
            prenode.next.pre.next = null;
            prenode.next.pre = prenode.next.pre.pre;
            size--;
            return ob;
        }
    }


    public Object get(int index){
        Node thisnode = this.findthis(index);
        return thisnode.e;
    }
    public int size(){
        return size;
    }
}

链表常用方法

1.指定位插入 add(int index, E e); 在index下标插入e元素
 2.指定位删除 remove(int index) ; 删除index下标的值
 删除第一次出现的o元素 remove(Object o)3.指定位修改 set(int index, E e) ; 将index下标的值修改为e
 4.指定位查询 get(int index) ; 返回index下标的元素值
 查询第一个元素getFirst()
 查询最末尾元素getLast()5.判空 isEmpty(); 对象为空返回true,非空返回false6.对象长度 size(); 返回对象的长度大小
 7.判断元素是否在对象中 contains(Object o); o在对象中返回true,不在返回false8.转换成数组 toArray();LinkedList对象转换成数组
 9.删除所有元素 clear();将对象中的元素全部删除
 10.查询元素第一次出现的下标indexOf(Object o );返回对象里第一次出现的o元素,没找到返回-1
  查询某元素最后一次出现的下标lastIndexOf(Object o)               
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

勇者六花i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值