链表

链表 SingleList

ArrayList的缺陷

在熟悉并且自己写了一个 ArrayList顺序表 的底层架构的时候 发现 ArrayList是利用数组来存储数据的

效率比较低:这里说两个例子

  1. 在插入以及删除的时候 ArrayList都需要移动剩余的元素
  2. 在开始的时候设置了初始的内存 后续需要扩容 这里也是效率低的表现

所以 ArrayList 不适合做任意位置插入以及删除比较多的场景

这里就引入链表结构

链表

链表的概念以及结构

定义:链表是一种 物理存储结构非连续的存储结构 ,数据元素的逻辑顺序是通过链表中的引用链接次序来实现的

首先在程序中定义链表需要定义两个属性 分别是 链表所带的值 以及下一个链表的地址

如图

image-20240904093219652

链表是通过下一个链表的地址来进行逻辑上的链接

所以

注意:

  1. 链式结构在逻辑上是连续的,但是在物理上不一定是连续的
  2. 显示中的节点一般都是从堆上申请出来的
  3. 从堆申请的空间,是按照一定的策略来分配的,两次申请的空间,可能连续也可能不连续
//链表中的一个字节 类
class ListNode{
    
    public int val;//链表所带的值
    public ListNode next;//下一个链表的地址
    
    //有参构造
    public ListNode(int val){this.val = val}
}

实际的链表结构非常多样 有以下8中

  1. 单向或者双向
  2. 带头或者不带头
  3. 循环或者非循环

将以上三种排列组合 可以得到8种链表结构 比如 单向带头不循环链表 也是我们目前学习的

链表的实现

class MySingleList{
    public ListNode head;//头节点
    
    //打印遍历
    public void display(){
        ListNode cur = head;
        while(cur!=null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }
    //从指定位置打印
    public void display(ListNode newHead){
        ListNode cur = newHead;
        while(cur!=null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }
    //size()
    public int size(){
        ListNode cur = head;
        int count = 0;
        while(cur!=null){
            cur = cur.next;
            count++;
        }
        return count;
    }
    //判断是否有key
    public boolean contains(int key){
        ListNode cur = head;
        while(cur!=null){
           if(cur.val==key){
               return true;
           }
           cur = cur.next
        } 
        return false;
    }
    //头插法
    public void addFirst(int data){
        ListNode node = new ListNode(data);
        node.next = head;
        head = node;
    }
    //尾插法
    public void addList(int data){
        ListNode node = new ListNode(data);
        ListNode cur = head;
        if(cur==null){
            head = node;
            return;
        }
        while(cur.next!=null){
            cur=cur.next;
        }
        cur.next = node;
    }
    //寻找index下标的上一个位置 方便插入
    private ListNode findIndexSubOne(int index){
        ListNode cur = head;
        while(index-1!=0){
            cur=cur.next;
            index--;
        }
        return cur;
    }
    //从index下标插入
    public void addIndex(int index,int data){
        if(index<0||index>size()){
            SyStem.out.print("index不合法");
            return;
        }
        if(index == 0){
            addFirst(data);
            return;
        }
        if(index==size()){
            addList(data);
            return;
        }
        ListNode cur = findIndexSubOne(int index);
        ListNode node = new ListNode(data);
        node.next = cur.next;
        cur.next = node;
    }
    private ListNode seachPrev(int index){
        ListNode cur = head;
        while(cur.next != null){
            if(cur.next.val == index){
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }
    //删除链表中第一个出现的key
    public void remove(int key){
        if(head==null){
            return null;
        }
        if(head.val == key){
            head = head.next;
            return;
        }
        ListNode cur = seachPrev(key);
        if(cur==null){
            return;
        }
        cur.next = cur.next.next
    }
    //删除所有key
    public void removeAllKey(int key){
        if(head==null){
            return;
        }
        ListNode prev = head;
        ListNode cur = head.next;
        while(cur!=null){
            if(cur.val==key){
                prev.next=cur.next;
                cur = cur.next;
            }else{
                prev = cur;
                cur = cur.next;
            }
        }
        if(head.val == key){
            head = head.next;
        }
    }
    public void clear(){this.head = null};
}

链表面试题 详见 IDEA

LinkedList的模拟实现

//单头双向无循环
public class MyLinkedList {

    static class ListNode{
        private int val;
        private ListNode prev;
        private ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode head;
    public ListNode last;


    //头插法
    public void addFirst(int data){
        ListNode node = new ListNode(data);
        if(head==null){
            this.head = node;
            this.last = node;
        }else{
            node.next = head;
            head.prev = node;
            head = node;
        }
    }
    //尾插法
    public void addLast(int data){
        ListNode node = new ListNode(data);
        if(head==null){
            this.head = node;
            this.last = node;
        }else{
            last.next = node;
            node.prev = last;
            last = node;
        }
    }
    public void cheakIndex(int index){
        if(index<0||index>size()){
            throw new indexOutOfException("index 不合法");
        }
    }
    private ListNode seachIndex(int index){
        ListNode cur = head;
        while(index!=0){
            cur=cur.next;
            index--;
        }
        return cur;
    }
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        cheakIndex(index);
        if(index == 0){
            addFirst(data);
            return;
        }
        if(index==size()){
            addLast(data);
            return;
        }
        ListNode node = new ListNode(data);
        ListNode cur = seachIndex(index);
        for (int i = 0; i < index; i++) {
            cur = cur.next;
        }
        cur.prev.next = node;
        node.prev = cur.prev;
        node.next = cur;
        cur.prev = node;
    }
    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        ListNode cur = head;
        while(cur!=null){
            if(cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }
    private ListNode findKeySubOne(int key){
        ListNode cur = head;
        while(cur!=null){
            if(cur.val == key){
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }
    //删除第一次出现关键字为key的节点
    public void remove(int key){
        if(head==null){
            return;
        }
        if(head.val == key){
            head = head.next;
            head.prev = null;
            return;
        }
        if(last.val == key){
            last = last.prev;
            last.next = null;
        }
        ListNode cur = findKeySubOne(key);
        cur.next.prev = cur.prev;
        cur.prev.next = cur.next;
    }
    //删除所有值为key的节点
    public void removeAllKey(int key){
        ListNode cur = head;
        while(cur!=null){
            if(cur.val == key){
                if(cur == head){
                    head = head.next;
                    if(head != null){
                        head.prev = null;
                    }else{
                        last = null;
                    }
                }else{
                    if(cur.next != null){
                        cur.next.prev = cur.prev;
                        cur.prev.next = cur.next;
                    }else{
                        last = last.prev;
                        last.next = null;
                    }
                }
                cur = cur.next;
            }
        }
    }
    //得到单链表的长度
    public int size(){
        ListNode cur = head;
        int count = 0;
        while(cur!=null){
            cur = cur.next;
            count++;
        }
        return count;
    }
    public void display(){
        ListNode cur = head;
        while(cur!=null){
            System.out.println(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }
    public void clear(){
        ListNode cur = head;
        while(cur!=null){
            ListNode newHead = cur.next;
            cur.val = 0;
            cur.prev = null;
            cur.next = null;
            cur = newHead;
        }
        head = null;
        last = null;
    }
}
posted @ 2024-09-27 10:05  Gargenone  阅读(6)  评论(0编辑  收藏  举报