LinkedList链表

LinkedList

在ArrayList中我们在顺序表中对其进行了模拟。通过代码,我们也就明白了。通过数组下标,寻找某个元素是非常的快捷键,但是向其中插入数数据,我们就要将插入的位置后的数据进行,向后挪移。这样的速度是非常慢的。
为了应对这种情况,就需要一种新的数据结构,也就是LinkedList。这种数据结构就类似于火车。对这种数据结构进行插入数据的操作,就类似于火车的车厢,向中间插入时,先跟前面一节车厢进行链接,然后链接后面一节车厢,通过锚定的方式进行连接。

在这里插入图片描述
画个图进行表示:
在这里插入图片描述
我们将它与数据结构结合。
在这里插入图片描述

我们看看java本身对于这个代码的处理。

		static class ListNode{
            public int val;//数据
            public ListNode next;//地址,也就是引用,类型我们定义成与类相同,这样我们就可以通过引用调取下一个车厢的数据和引用
            public ListNode(int val){
                    this.val=val;
            }
            public ListNode(){
            }
        }

在这里插入图片描述
好了到了这一步已经将链表的大体结构解释的差不多了。诺还有不懂的,可以私信我。可以免费给大家详细讲述。

LinkedList

如何自我实现

框架流程:

public class SingleLinkedList {
//头插法
public void addFirst(int data){
}
//尾插法
public void addLast(int data){
}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
return false;
}
//删除第一次出现关键字为key的节点
public void remove(int key){
}
//删除所有值为key的节点
public void removeAllKey(int key){
}
//得到单链表的长度
public int size(){
return -1;
}
}

这里我贴上我的实现

		public ListNode head;
       public int cont;
        static class ListNode{
            public int val;
            public ListNode next;
            public ListNode(int val){
                    this.val=val;
            }
            public ListNode(){

            }
        }
        //头插法
        public void addFirst(int data){

                ListNode node=new ListNode(data);
                node.next=head;
                head=node;
                cont++;

        }
        //尾插法
        public void addLast(int data){
            ListNode listNode=new ListNode(data);
            if (head==null){
                head=listNode;
                return;
            }
            ListNode cur=head;
            while (cur.next!=null){
                cur=cur.next;
            }
            cur.next=listNode;
        }
        //任意位置插入,第一个数据节点为0号下标
        public void addIndex(int index,int data){
            if (index<0&&index>cont){
                throw  new ListIndexOutOfException("位置错误");
            }
            if (index==0){
                addFirst(data);
                return ;
            }
            if (index==cont){
                addLast(data);
                return;
            }
            int count=0;
            ListNode cur=head;
            while (count!=index-1){
                cur=cur.next;
                count++;
            }
            ListNode listNode=new ListNode(data);
            listNode.next=cur.next;
            cur.next=listNode;

        }
        //查找是否包含关键字key是否在单链表当中
        public boolean contains(int key){
            if (head==null){
                return false;
            }
            ListNode cur=head;
            while (cur.next!=null){

                if (cur.val==key){
                    return true;
                }
                cur=cur.next;
           }
            return false;

        }
        //删除第一次出现关键字为key的节点
        public void remove(int key){
            if (head==null){
                return;
            }
            if (head.val== key){
                head=head.next;
                return;
            }
            ListNode cur=head;
            while (cur.next!=null){
                if (cur.next.val==key){
                  break;
                }
                cur=cur.next;
            }
            if (cur.next==null){
                return;
            }
            cur.next=cur.next.next;


        }
        //删除所有值为key的节点
        public void removeAllKey(int key){
            if (head==null){
                return;
            }
            if (head.val==key){
                head=head.next;
                return;
            }
            ListNode cur=head.next;
            ListNode provt=head;
            while (cur!=null){
                if (cur.val==key){
                    provt.next=cur.next;
                }
                provt=cur;
                cur=cur.next;
            }
        }
        //得到单链表的长度
        public int size(){
            return cont;
        }
        public void display(){
            ListNode cur=head;
            while (cur!=null){
                System.out.println(cur.val+" ");
                cur=cur.next;

            }
        }

        public void clear(){
            head=null;

        }

到此我们就自我实现了一个单链表,然而我相信你们也就看的出来,单链表是一个只能前进不能后退的链表,那么如何实现倒退呢?其实可以在节点中除next之外加一个类似next作用的链接器。如此就可以,我们将它命名为frist,让它去记录上一个节点的地址。

插入效率的解决

通过上述的任意插入,我们可以看到,我们并没有挪移后面的元素,而是暴力直接插入所在位置的地方。相当于成语:横插一脚,再次我们最多在链表末尾插入,也就遍历一遍,而数组诺是在头插入就是在遍历一遍的同时,还得挪移一遍。这样插入的效率大大提高了

//任意位置插入,第一个数据节点为0号下标
        public void addIndex(int index,int data){
            if (index<0&&index>cont){
                throw  new ListIndexOutOfException("位置错误");
            }
            if (index==0){
                addFirst(data);
                return ;
            }
            if (index==cont){
                addLast(data);
                return;
            }
            int count=0;
            ListNode cur=head;
            while (count!=index-1){
                cur=cur.next;
                count++;
            }
            ListNode listNode=new ListNode(data);
            listNode.next=cur.next;
            cur.next=listNode;

        }

技术细节

源代码:
在这里插入图片描述

返回值方法解释
booleanadd(E e)尾插 e
voidadd(int index, E element)将 e 插入到 index 位置
booleanaddAll(Collection<? extends E> c)尾插 c 中的元素
Eremove(int index)删除 index 位置元素
booleanremove(Object o)删除遇到的第一个 o
Eget(int index)获取下标 index 位置元素
Eset(int index, E element)将下标 index 位置元素设置为 element
voidclear()清空
booleancontains(Object o)判断 o 是否在线性表中
intindexOf(Object o)返回第一个 o 所在下标
intlastIndexOf(Object o)返回最后一个 o 的下标
ListsubList(int fromIndex, int toIndex)截取部分 list

小结

  1. LinkedList实现了List接口
  2. LinkedList的底层使用了双向链表
  3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
  4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
  5. LinkedList比较适合任意位置插入的场景

ArrayList和 LinkedList的区别

不同点ArrayListLinkedList
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持O(1)不支持:O(N)
头插需要搬移元素,效率低O(N)只需修改引用的指向,时间复杂度为O(1)
插入空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁

其他文章接口

1.String方法(重要,对于操作字符串有巨大的帮助)

文章链接

2.java常用的接口及其方法(包含拷贝,比较,排序,构造器)

文章链接

3.初阶数据结构

3.1 顺序表:ArrayList

文章链接

3.2 链表:LinkedList

文章链接

3.3 栈:Stack

文章链接

3.4 队列:Queue

文章链接

3.5 二叉树:Tree

文章链接

3.6 优先级队列:PriorityQueue(堆排序)

文章链接

3.7 Map和Set

HashMap和HashSet,TreeMap和TreeSet
文章链接

4. 排序(7种方式)

4.1 插入排序(两种)

4.2 选择排序(两种)

4.3 快速排序

4.4 堆排序

里面有堆排序的实现和逻辑
文章链接

4.5 归并排序

5.多线程

文章链接

6.网络编程

7.HTML

8.数据库Mysql

文章链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值