Java資料結構和演算法( 二 ) ## 數組

來源:互聯網
上載者:User

標籤:已耗用時間   擴容   for   display   find   為什麼   綜述   特殊   index   

目錄

  • 數組綜述
  • Java中的數組
    • 建立數組
    • 訪問數組
    • 初始化數組
    • 有序數組
    • 線性尋找
    • 二分尋找
    • 有序數組的優缺點
  • 大O標記法(order of)
  • 為什麼不用資料解決一切
- 小結數組綜述

    數組是最廣泛的資料存放區結構,其中還有一種特殊數組(有序數組),下面講解下插入、查詢、刪除相關的注意事項

  • 插入: 新資料總是插在數組第一個空位上,由於已有資料項目個數已知,所以空位的具體位置很容易得知,然而查詢和刪除卻沒有那麼快。當不允許插入重複值的模式下,還需要將演算法計算是否存在資料項目。
  • 尋找: 若是無重複項模式,必須平均搜尋一半的資料項目來尋找特定資料項目。找數組頭部的資料項目快,找數組尾部的資料項目慢。若重複模式,必須從頭尋找到尾。
  • 刪除: 只有找到特定資料項目後才能進行刪除操作(要麼該資料項目被替換,要麼變為空白)。刪除演算法中假設不允許有洞(一個或多個空單元後面存在非空資料項目),如果刪除演算法允許有洞,則其他演算法變得很複雜,因為要判斷非空降低效率。因此非空資料項目必須連續,不能有洞。在無重複項模式下尋找平均N/2個資料項目+移動剩下的N/2個資料項目來補洞。總共是N步。
  • 重複值問題:
    • 重複項模式下尋找演算法: 重複項使尋找演算法複雜,匹配上一個後,還得考慮是否繼續尋找可能的匹配,直到最後一個資料項目(所有藍眼睛的人和第一個藍眼睛的人的區別)。通常操作需要N步。
    • 重複項模式下插入演算法: 和不重複項模式一樣,只需要一步。
    • 重複項模式下刪除演算法:若是刪除第一個特定的資料項目,操作步驟平均是N/2次尋找+N/2移動,若是刪除所有特定的資料項目,需要檢查N個資料項目+移動多餘N/2個資料項目,操作的平均時間取決於重複項的個數和分布。

表格區別重複與無重複模式的區別

操作 不允許重複 允許重複
尋找 N/2次比較 N次比較
插入 無比較、一次移動 一次移動
刪除 N/2次比較、N/2次移動 N次比較、多於N/2次移動
Java中的數組建立數組

int[] intArray = new int[]{};
int[] intArray = new int[2];

訪問數組

數組資料項目通過下標訪問,下標從0開始,止於長度減1。若下標不在這個範圍訪問數組,則拋出Array Index Out of Bounds的執行階段錯誤。

初始化數組

int[] intArray = {1,2,3,4,5};
int[] intArray = new int[]{1,2,3,4,5};

程式碼範例

github 地址

public class HightArray {    /** 聲明一個數組 */ private long[] a;    /** 聲明變數記錄資料項目個數 */ private int nElemts;    /** 構造方法用於初始化數組和資料項目總數 */    public HightArray(int max){ a = new long[max]; nElemts = 0; }    public void insert(long value){ a[nElemts] = value; nElemts ++ ; }    public boolean find(long searchKey){        int j;        for (j=0;j<nElemts;j++){ if(a[j]==searchKey){ break; } }        return j == nElemts;    }    public boolean delete(long value){        int j;        for (j=0; j<nElemts; j++){ if(a[j]==value){ break; } }        if(j == nElemts) { return false; }        else {            for (int k=j; k<nElemts; k++){ a[k] = a[k+1]; }            nElemts--;            return true;        }    }    public void display(){                   System.out.println(Arrays.stream(a).mapToObj(String::valueOf).collect(Collectors.joining(" ")));    }}

測試類別>>>

public class HightArrayTest {    @Test public void test(){        int maxSize = 100;        HightArray hightArray = new HightArray(maxSize){{            insert(77); insert(99); insert(44); insert(55); insert(66);            insert(22); insert(88); insert(11); insert(00); insert(33);        }};        hightArray.display();        int searchKey = 35;        System.out.println(hightArray.find(searchKey)?"Found ":"Can‘t find " + searchKey);        hightArray.delete(00); hightArray.delete(55); hightArray.delete(99);        hightArray.display();    }}
有序數組

    數組中的資料項目按照關鍵字升序排列。當向此數組中插入資料項目時,需要為插入操作找到正確位置,在稍小位置和稍大位置之間,然後將稍大位置至末尾的資料項目往後移動一位騰出位置。
    這中順序排列的好處就是可以通過二分尋找顯著提高查詢速度,但是降低了插入的速度,畢竟要騰出坑位。

線性尋找

    線性尋找就是依次向後,尋找匹配。而在有序數組中當匹配到一個合適的資料項目就退出尋找。

二分尋找

    二分尋找就是一半一半的找,這種查詢比線性查詢快很多,尤其對大數組來說。

有序數組程式碼範例

github 地址

public class OrderArray {    private long[] a;    private int nElems;    public OrderArray(int maxSize){ a = new long[maxSize]; nElems = 0; }    public int size(){ return nElems; }    public void insert(long value){        int j ;        for (j = 0; j < nElems; j++) { if(a[j] > value) { break; } }        for(int k=nElems; k>j; k--){ a[k] = a[k-1]; }        a[j] = value;        nElems++;    }    public int find(long searchKey){        int lowerBound = 0, upperBound = nElems -1, curIndex;        while (true){            if(lowerBound > upperBound){ return nElems; }            curIndex = (lowerBound + upperBound)/2;            if(a[curIndex] == searchKey) { return curIndex; }            else if (a[curIndex] < searchKey){ lowerBound = curIndex + 1; }            else { upperBound = curIndex - 1; }        }    }    public boolean delete(long value){        int j = find(value);        if(j == nElems) { return false; }        for (int k = j; k < nElems; k++){ a[k] = a[k+1]; }        nElems--;        return true;    }    public void display(){        System.out.println(Arrays.stream(a).mapToObj(String::valueOf).collect(Collectors.joining(" ")));    }}

測試類別>>>

public class OrderArrayTest {    @Test public void test(){        int maxSize = 100;        OrderArray orderArray = new OrderArray(maxSize){{            insert(77); insert(99); insert(44); insert(55); insert(22);            insert(88); insert(11); insert(00); insert(66); insert(33);        }};        int searchKey = 55;        System.out.println(orderArray.find(searchKey)!=orderArray.size()?"Found":"Can‘t find" + searchKey);        orderArray.display();        orderArray.delete(00); orderArray.delete(55); orderArray.delete(99);        orderArray.display();    }}
有序數組的優缺點
  • 優點: 二分尋找比無序資料快。
  • 缺點: 插入需要尋找,尋找後需要將靠後的資料項目整體往後移動。刪除操作都需要補洞。
大O標記法(order of)
演算法 已耗用時間
線性尋找(從頭到尾) O(N)
二分尋找(一半一半) O(LogN)
無序數組插入(僅一次) O(1)
有序數組插入(查詢+移動) O(N)
無序數組刪除(查詢+補洞) O(N)
有序數組刪除(查詢+補洞) O(N)
為什麼不用資料解決一切

    一個無序數組插入(O(1)時間),查詢卻花費(O(N)時間)。一個有序數組查詢花費(O(LogN)時間),但是插入缺花費(O(N)時間)。而刪除都需要花費(O(N)時間)。所以需要一種資料結構插入、查詢、刪除都很快,理論上(O(1)或者O(LogN)時間),而且數組一旦建立,其大小被固定,擴容不便,若空間大了又會浪費。

小結
  • 無序數組可以快速插入,但查詢和刪除比較慢。
  • 有序數組可以使用二分法尋找。
  • 線性尋找需要的時間和資料項目個數成正比。
  • 二分法尋找需要的時間和資料項目個數的對數成正比。
  • O(1)演算法最好、O(LogN)次之、O(N)一般、O(N*N)最差。
    

Java資料結構和演算法( 二 ) ## 數組

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.