首页 > 其他分享 >链表

链表

时间:2024-09-27 10:01:44浏览次数:1  
标签:head ListNode cur int next 链表 null

链表 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;
    }
}

标签:head,ListNode,cur,int,next,链表,null
From: https://www.cnblogs.com/ljy2003/p/18435114

相关文章

  • 算法记录——链表
    2.链表2.1判断是否是回文链表1.方法一:利用栈反转链表/***Definitionforsingly-linkedlist.*publicclassListNode{*intval;*ListNodenext;*ListNode(){}*ListNode(intval){this.val=val;}*ListNode(intval,Lis......
  • 【数据结构.总集篇】第一章 链表
    文章目录1.链表1.1线性表1.2顺序表1.3单链表链表简介单链表的介绍线性表的链式存储头节点概念为何引入头结点单链表的基本操作创建一个单链表初始化头插法尾插法删除操作打印总代码1.4单链表循环1.5双链表双链表的定义双链表上的操作初始化插入操作头插法尾插法......
  • 925 jdbc js 链表(2)
    jdbc基础复习一遍js声明函数行为绑定onclick单击ondbclick双击script标签放head以外也可以script必须写双标签变量声明都用var弱类型console。log1==1true1==‘1’trueprompt弹窗输入for循环js创建对象......
  • 【LeetCode Hot 100】19. 删除链表的倒数第N个结点
    题目描述由于单向链表只能从头往后遍历,所以无法向数组那样的随机存取结构一样进行下标运算,也无法从链表尾向前数n个结点。本题有两个思路,个人觉得都比较简单。可以先遍历一遍链表得到链表的长度len,然后再从头往后数len-n个结点就是所求结点。可以使用快慢指针,快指针先移动n......
  • 只用单链表的方式判断一个链表是否为回文链表
    思路寻找链表的中点:使用快慢指针的方法,快指针每次移动两步,慢指针每次移动一步。当快指针到达链表末尾时,慢指针正好位于链表的中间。反转后半部分链表:从中点开始反转链表的后半部分。比较前半部分和反转后的后半部分:逐一比较两个部分的节点值,如果所有对应的节点值都相同,则......
  • 数据结构:双向链表(Doubly Linked List篇)手把手带你入门数据结构~
    文章目录前言一、双向链表的概念1.结构特点:2.优点:二、双向链表的实现1.双向链表的结构2.双向链表初始化3.双向链表销毁4.双向链表打印5.双向链表尾插6.双向链表头插7.双向链表尾删8.双向链表头删9.双向链表查找10.双向链表指定位置插入11.双向链表指定位置......
  • 【链表操作】前驱和后继
    题目描述设计函数void prevnext(structnode*head,charx);,在以head为头指针的非空链表中,找到数据域值为x的结点,输出该结点的前一个结点和后一个结点的数据域值,如果该结点没有前驱结点(即该结点为第1个结点),则以-1代替,如果该结点没有后继结点(即该结点为尾结点),也以-1代替......
  • 简单易懂理解:数仓——拉链表
    1.什么是拉链表拉链表就像衣服的拉链一样重要,实用性非常强,使用频率非常高。所谓的拉链,就是历史记录,记录一个事物的开始到结束所变化的所有信息。“拉链表是一种针对数据仓库设计中表存储数据的方式而定义的数据模型,它有点类似于快照,‌它通过记录每个数据项的生效日期和失效......
  • 链表的回文结构
    对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。测试样例:1->2->2->1返回:true什么是回文?:回文是指从前向后读和从后向前读都相同的字符......
  • 数据结构:单链表
    单链表单链表概念与结构节点链表的性质单链表的打印实现单链表创建新的节点在末尾插入数据在头部插入数据删除尾部数据删除第一个节点在链表中寻找目标数据在指定位置之前插入数据在指定位置之后插⼊数据删除pos结点删除pos之后的结点销毁链表单链表测试单链表概念与......