Java数据结构和算法之第五章、LinkedList与链表

一、ArrayList的缺陷

public class ArrayList extends AbstractList
            implements List, RandomAccess, Cloneable, java.io.Serializable {
        // ...
// 默认容量是10
        private static final int DEFAULT_CAPACITY = 10;
        //...
// 数组:用来存储元素
        transient Object[] elementData; // non-private to simplify nested class access
        // 有效元素个数
        private int size;

        public ArrayList(int initialCapacity) {
            if (initialCapacity > 0) {
                this.elementData = new Object[initialCapacity];
            } else if (initialCapacity == 0) {
                this.elementData = EMPTY_ELEMENTDATA;
            } else {
                throw new IllegalArgumentException("Illegal Capacity: " +
                        initialCapacity);
            }
        } // ...
    }

由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。因此:java集合中又引入了LinkedList,即链表结构。


二、链表

2.1链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。(逻辑上连续物理上不连续)
Java数据结构和算法之第五章、LinkedList与链表_第1张图片

实际中链表的结构非常多样,通过节点组成。以下情况组合起来就有8种链表结构:
1.单向 带头 循环链表   2.单向 带头 非循环链表   3.单向 不带头 循环链表 4.单向 不带头 非循环链表 

5.双向 带头 循环链表   6.双向 带头 非循环链表   7.双向 不带头 循环链表   8.双向 不带头 非循环链表

2.1.1单向和双向

Java数据结构和算法之第五章、LinkedList与链表_第2张图片

2.1.2带头或者不带头

Java数据结构和算法之第五章、LinkedList与链表_第3张图片
 2.1.3循环或者非循环

Java数据结构和算法之第五章、LinkedList与链表_第4张图片

 2.1.4重点

1.无头单向非循环链表

结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

Java数据结构和算法之第五章、LinkedList与链表_第5张图片

2. 无头双向链表

在Java的集合框架库中LinkedList底层实现就是无头双向循环链表

2.2链表的实现

// 1、无头单向非循环链表实现
public class IndexOutOfBounds extends RuntimeException{
    public IndexOutOfBounds(String message){
        System.out.println(message);
    }
}

   public class MySingleList {
    //节点的创建
    class ListNode{
        //值域
        public int val;
        //引用变量
        public ListNode next;
        public ListNode(int val){
            this.val=val;
        }
    }
    //永远指向头节点
    public ListNode head;
    public void createList(){
        ListNode node1=new ListNode(12);
        ListNode node2=new ListNode(23);
        ListNode node3=new ListNode(34);
        ListNode node4=new ListNode(45);
        ListNode node5=new ListNode(56);

        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;
        head.next=node1;
    }
    public void show(){
        ListNode cur=head;
        while(cur!=null){
            System.out.println(cur.val);
            cur=cur.next;
        }
        System.out.println();
    }
    //头插法
    public void addFirst(int data){
        ListNode cur=new ListNode(data);
        cur.next=head;
        head=cur;
    }
    //尾插法
    public void addLast(int data){
        ListNode node=new ListNode(data);
        if(head==null){
            head=node;
            return ;
        }
        ListNode cur=head;
        while(cur!=null){
            cur=cur.next;
        }
        //cur 指向的节点是尾巴节点
        cur.next=node;
    }
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        int len=size();
        if(index<0||index>len){
            throw new IndexOutOfBounds("任意位置插入数据的时候,index的位置不合法:"+index);
        }
        if(index==0){
            addFirst(data);
            return ;
        }
        if(index==len){
            addLast(data);
            return ;
        }
        ListNode node=new ListNode(data);
        ListNode cur=findIndex(index);
        node.next=cur.next;
        cur.next=node;
    }
    private ListNode findIndex(int index){
        ListNode cur=head;
        while(index-1!=0){
            cur=cur.next;
            index--;
        }
        return cur;
    }
    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        ListNode cur=head;
        while(cur!=null){
            //如果value值为空,需要使用equals方法比较
            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 prev=searchPrev(key);
        if(prev==null){
            System.out.println("没有这个数据!");
            return ;
        }
        ListNode del=prev.next;
        prev.next=del.next;
    }
    private ListNode searchPrev(int key){
        ListNode prev=head;
        while(prev.next!=null){
            if(prev.next.val==key){
                return prev;
            }
            else{
                prev=prev.next;
            }
        }
        return null;
    }
    //删除所有值为key的节点
    public void removeAllKey(int key){
        if(head==null){
            return ;
        }
        //第一种删除头节点方法
        /*
        * while(head.val==key){
        *   head=head.next;
        * }
        * */
        ListNode cur=head.next;
        ListNode prev=head;
        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 int size(){
        int count=0;
        ListNode cur=head;
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        return count;
    }
    public void clear() {
        //this.head=null;
        while(head!=null){
            ListNode HeadNext=head.next;
            head.next=null;
            head=HeadNext;
        }
    }
}

你可能感兴趣的:(Java数据结构和算法,java,数据结构,链表,leetcode,算法)