資料結構——列表

karspb發表於2021-09-09

列表是常用的資料結構, 也是佇列和棧的基礎。本文將介紹兩種列表的簡單實現:陣列列表和連結串列。

public interface IList {
    /**
     * 插入
     * @param i 位置
     * @param data 要插入的資料
     */
    void insert(int i, T data);

    /**
     * 獲取
     * @param i 位置
     * @return i 位置上的元素
     */
    T get(int i);

    /**
     * 刪除
     * @param i 位置
     * @return 被刪除的元素
     */
    T delete(int i);

    /**
     * 列表內元素的數量
     * @return 數量
     */
    int size();

    /**
     * 列表是否為空
     * @return
     */
    boolean isEmpty();
}

(測試用例不完全覆蓋)
public class MyArrayList implements IList {

    private T[] datas;
    private int count = 0;
    private int capacity;

    public MyArrayList(int capacity) {
        datas = (T[]) new Object[capacity];
        this.capacity = capacity;
    }

    @Override
    public void insert(int i, T data) {
        if (count == capacity)
            throw new RuntimeException("列表已滿");
        if (i  count)
            throw new RuntimeException("下標非法");
        if (i == count)
            datas[count++] = data;
        else {
            System.arraycopy(datas, i, datas, i + 1, count - i);
            datas[i] = data;
            count++;
        }
    }

    @Override
    public T get(int i) {
        if (i = count)
            throw new RuntimeException("下標非法");
        return datas[i];
    }

    @Override
    public T delete(int i) {
        if (i = count)
            throw new RuntimeException("下標非法");
        T tmp = datas[i];
        System.arraycopy(datas, i + 1, datas, i, count - i);
        count--;
        return tmp;
    }

    @Override
    public int size() {
        return this.count;
    }

    @Override
    public boolean isEmpty() {
        return this.size() == 0;
    }
}

(用例不完全覆蓋)
public class MyLinkedList implements IList {

    private int count = 0;
    private Node head = new Node();
    private class Node{
        T data;
        Node next;

        public Node() {
        }

        Node(T data, Node next) {
            this.data = data;
            this.next = next;
        }
    }

    @Override
    public void insert(int i, T data) {
        if (i  this.count)
            throw new RuntimeException("下標非法");
        Node prev = getNode(i - 1);
        prev.next = new Node(data, prev.next);
        count++;
    }

    @Override
    public T get(int i) {
        if (i = count)
            throw new RuntimeException("下標非法");
        return this.getNode(i).data;
    }

    @Override
    public T delete(int i) {
        if (i = count)
            throw new RuntimeException("下標非法");
        Node prev = getNode(i - 1);
        Node node = prev.next;
        prev.next = node.next;
        count--;
        return node.data;
    }

    @Override
    public int size() {
        return this.count;
    }

    @Override
    public boolean isEmpty() {
        return this.size() == 0;
    }

    /**
     * 得到第i個位置的元素
     * 注意k的初始條件和while迴圈遞增
     * @param i 若i為-1,返回head
     * @return
     */
    private Node getNode(int i) {
        int k = - 1;
        Node res = head;
        while (k++ 
總結

陣列列表的插入、刪除的時間複雜度是O(n),查詢的時間複雜度是O(1);
連結串列的插入、刪除的時間複雜度是O(1),查詢的時間複雜度是O(n);
因此,讀多寫少用陣列列表,寫多讀少用連結串列

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2001/viewspace-2808528/,如需轉載,請註明出處,否則將追究法律責任。

相關文章