1. 程式人生 > >線性表-順序結構

線性表-順序結構

  • 應昨天,今天學習線性表的順序結構
  • 什麼是線性表:線性表是一種典型的線性結構,是由n個元素組成的有限序列,比如字母表,點名冊
  • 對於一個非空的線性表,邏輯結構特徵如下

    • 有且僅有一個開始節點a1,沒有直接前趨節點,有且僅有一個直接後繼節點a2
    • 有且僅有一個結束節點an,沒有直接後繼節點,有且僅有一個直接前趨節點a(n-1)
    • 其餘節點均都有一個前趨節點和一個後繼節點
    • 資料元素的型別都必須相同

markdown_img_paste_20181202080731240

  • 線性表-順序表的結構

    • 順序表就是按照順序儲存方式儲存的線性表,該線性表的節點按照邏輯次序依次存放在計算機的一組連續的儲存單元中(Array):java中實現為ArrayList
    • 下面實現,下標依舊是從0開始的,下面的實現並沒有加入額外的非法輸入控制,只是實現了一個大概的邏輯
    public class MyArrayList<T> {
        //預設大小
        private static final int DEFAULT_SIZE = 20;
        //存放元素的陣列物件
        private Object[] elements ;
        private int length;
        public MyArrayList() {
            elements = new Object[DEFAULT_SIZE];
        }
        public MyArrayList(int initSize) {
            elements = new Object[initSize];
        }
        //追加節點
        public void staticAdd(T element){
            if (! judgeLength()){
                throw new RuntimeException("元素已滿:" + length);
            }
            elements[length] = element;
            length++;
        }
        //追加節點
        public void dynamicAdd(T element){
            if (! judgeLength()){
                dilatation();
            }
            staticAdd(element);
        }
        //插入節點
        public void staticInsert(T element, int index){
            if (! judgeLength()){
                throw new RuntimeException("元素已滿:" + length);
            }
            Object[] tmp = new Object[length - index];
            System.arraycopy(elements,index,tmp,0,length-index);
            elements[index] = element;
            System.arraycopy(tmp,0,elements,index+1,length-index);
            length++;
        }
        //獲取節點
        public T get(int index){
            return (T) elements[index];
        }
        //動態插入
        public void dynamicInsert(T element, int index){
            if (! judgeLength()){
                dilatation();
            }
            staticInsert(element,index);
        }
        //刪除節點
        public void delete(T element){
            int i = findFirst(element);
            delete(i);
        }
        //刪除節點
        public void delete(int index){
            Object[] tmp = this.elements;
            System.arraycopy(tmp,index + 1,elements,index,length - index + 1);
            length -- ;
        }
        //刪除集合中全部與element相同的元素
        public void deleteAll(T element){
            int i = 0;
            while (i >= 0){
                i = findFirst(element);
                if (i >= 0){
                    delete(i);
                }
            }
        }
        //修改節點
        public void update(T element , int index ){
            elements[index] = element;
        }
        //查詢節點
        private int findFirst(T element){
            for (int i = 0; i < length; i++) {
                if (element.equals(elements[i])){
                    return i;
                }
            }
            return -1;
        }
        //判斷空間是否夠用
        private boolean judgeLength(){
            if (length < elements.length){
                return true;
            }
            return false;
        }
        //擴容
        private void dilatation(){
            Object[] tmp = elements;
            elements = new Object[length * 2];
            System.arraycopy(tmp,0,elements,0,length);
        }
        //返回列表長度
        public int getLength() {
            return length;
        }
        @Override
        public String toString() {
            StringBuffer buffer = new StringBuffer(length * 2 + 5);
            buffer.append("[");
            for (int i = 0; i < length; i++) {
                if (i == length - 1) {
                    buffer.append(elements[i] + "]");
                    break;
                }
                buffer.append(elements[i] + ",");
            }
            return buffer.toString();
    //        return Arrays.toString(elements);
        }
    }
  • 在實現的過程中,我遇到了一個問題.那就是System.arraycopy快,還是說我們仿照的ArrayList中使用的Arrays.copy快,所以我做了一個測試

    int nano = Instant.now().getNano();
    MyArrayList<Integer> a  = new MyArrayList<>();
    for (int i = 0; i < 10000000; i++) {
        a.dynamicAdd(i);
    }
    System.out.println(a.getLength());
    System.out.println(Instant.now().getNano() - nano);
  • 結果

    一千萬add時候
      MyArrayList
        10000000
        532000000
      ArrayList
        10000000
        427000000
    五千萬add的時候  
      MyArrayList
          50000000
          609000000
      ArrayList
          50000000
          計算不出來的負數
  • 算是一個結果吧,當資料很大的時候System.copy比Arrays.copy要快點,網上很多求證帖子得出瞭如下的結論

    當陣列元素個數不是很大時,for>clone>System.arraycopy>Arrays.copyof。
    當陣列元素個數很大時,System.arraycopy>clone>Arrays.copyof>for。
  • 並且新收穫了一個知識點System.arraycopy是淺複製的,只是複製了物件的引用而已,所以以後使用這個方法的時候就必須注意了

    public class Test {
        int i ;
        public Test(int i) {
            this.i = i;
        }
        public static void main(String[] args) {
            Test[] t = new Test[10];
            t[0] = new Test(0);
            t[1] = new Test(1);
            t[2] = new Test(2);
            Test[] t2 = new Test[10];
            System.arraycopy(t,0,t2,0,t.length);
            print(t);
            print(t2);
            t2[0].i = 222;
            print(t);
            print(t2);
        }
    
        private static void print(Test[] t) {
          ...
        }
        /**
         *  如下列印的是Test的物件,也能看出來是同一個物件
         * [[email protected], [email protected], [email protected], null, null, null, null, null, null, null]
         * [[email protected], [email protected], [email protected], null, null, null, null, null, null, null]
         * [[email protected], [email protected], [email protected], null, null, null, null, null, null, null]
         * [[email protected], [email protected], [email protected], null, null, null, null, null, null, null]
         */
    }
  • 結果為

    0,1,2
    0,1,2
    222,1,2
    222,1,2
  • 明天學習線性表的連結串列結構,在這寫出,以示督促自己