數據結構——鏈表List、ArrayList、LinkedList


title: '數據結構——鏈表List、ArrayList、LinkedList ’
date: 2019-11-16 10:42:41
categories:

  • 數據結構
    tags:
  • 數據結構
  • 鏈表

抽象數據類型ADT

  • 是帶有一組操作的一些對象的集合

一種特別的抽象類型——表ADT

什麼是一個表呢?

最簡單的一個整數表 -> 由一羣整數構成的一個數組,可以看做是一張表

//表的簡單數組實現
int[] arr = new int[10];
...
//對一個表的擴容
int[] newArr = new int[arr.length*2];
for(int i=0;i<arr.length;i++){
    newArr[i] = arr[i];
}
arr =newArr;

數組的實現是線性執行的,對其中的查找操作也是常數時間,但是插入和刪除卻潛藏着昂貴的開銷。兩種情況最壞的情況都是O(N)

簡單鏈表

於是爲了避免插入和刪除的開銷就有了,鏈表的出現。鏈表是由一個個節點組成的,並且不限制需要存儲在一段連續的內存中。

節點

每一個節點均含有一個表元素、一個包含了後繼節點的鏈Link。

//鏈表節點
LinkNode class{
    Object var;
    LinkNode next;
}

對於鏈表中節點的刪除與插入,只需要常數時間。

首先找到要刪除的節點位置或者要插入的節點位置

刪除 該節點的前一個節點,指向該節點的後繼節點就可以了

插入 找到插入節點的前一個節點,將前一個節點的後繼節點用該節點指向,將前一個節點指向該節點

雙鏈表

對於單鏈表的不足之處在於,對尾節點的刪除,需要先找到最後節點的項,把他改爲next鏈改爲null,然後再更新持有最後節點的鏈。但是在經典鏈表中,每個節點均存儲的是下一個節點,並不提供最後一個節點的前驅節點的任何信息。

單鏈表的刪除需要靠輔助節點,而雙向鏈表則可以直接刪除

對於此,就想到了雙向鏈表,讓每一個節點持有一個指向它在表中的前驅節點的鏈。

JAVA中 Collections API中的表

集合的概念在java中用Collection接口來抽象,它存儲一組類型相同的對象

//源碼參考
public interface Collection<E> extends Iterable<E> {
 	int size();
     boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator(); //該方法繼承於Iterable接口內的Iterator方法
    boolean add(E e);
    boolean remove(Object o);
}

Collection接口對Iterator接口進行了擴展,實現Iterator接口中那些類擁有增強的for循環。

//Iterator接口
public interface Iterator<E> {
    boolean hasNext(); 
    E next();
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

List接口、ArrayList類、LinkedList類

List接口 既是表的抽象,他繼承了Collection

public interface List<E> extends Collection<E> {
     int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator(); 
    Object[] toArray();

    
    E get(int index);
    E set(int index, E element);
    void add(int index, E element);
    E remove(int index);
    
    / ** 
        *從列表中的指定位置開始,以正確的
        *順序返回列表中元素的列表迭代器。
        *指定的索引表示首次調用{@link ListIterator#next next}將返回的第一個元素。 
        *初次調用{@link ListIterator#previous previous}*返回具有指定索引減一的元素。 
        * * @param index從列表迭代器返回的第一個元素的索引(通過調用{@link ListIterator#next next}* @在此列表中的元素上返回列表迭代器(按適當的順序) ,從列表中的指定位置開始
        * @throws IndexOutOfBoundsException如果索引超出範圍
        *{@code index <0 || index> size()}* /
    ListIterator<E> listIterator(int index); 

ArrayList和LinkedList是對List的兩種實現

ArrayList 單鏈表

  • 是一種可增長的數組實現

  • 優點在於,對get和set的調用花費常數時間

  • 缺點是add和remove的代價昂貴

ArrayList的實現與分析

LinkedList 雙鏈表

  • 是一種雙鏈表的實現
  • 優點在於,add和remove的開銷小
  • 並且提供了addFirst、removeFirst、addLast、removeLast、getFirst、getLast等方法
  • 缺點則是他不容易進行索引,對get的調用則是昂貴的

未完待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章