資料結構之數組,資料結構數組
數組是應用最廣泛的一種資料結構,常常被植入到程式設計語言中,作為基礎資料型別 (Elementary Data Type)使用,因此,在一些教材中,數組並沒有被當做一種資料結構單獨拿出來講解(其實數組就是一段連續的記憶體,即使在實體記憶體中不是連續的,在邏輯上肯定是連續的)。其實沒必要在概念上做糾纏,數組可以當做學習資料結構的敲門磚,以此為基礎,瞭解資料結構的基本概念以及構建方法
資料結構不僅是資料的容器,還要提供對資料的操作方法,比如檢索、插入、刪除、排序等
無序數組
下面我們建立一個類,對數組的檢索、插入、刪除、列印操作進行封裝,簡便起見,我們假設數組中沒有重複值(實際上數組可以包含重複值)
public class Array { private String [] strArray; private int length = 0; //數組元素個數 //構造方法,傳入數組最大長度 public Array(int max){ strArray = new String [max]; } //檢測數組是否包含某個元素,如果存在返回其下標,不存在則返回-1 public int contains(String target){ int index = -1; for(int i=0;i<length;i++){ if(strArray[i] == target){ index = i; break; } } return index; } //插入 public void insert(String elem) { strArray[length] = elem; length++; } //刪除某個指定的元素值,刪除成功則返回true,否則返回false public boolean delete(String target){ int index = -1; if((index = contains(target)) !=-1){ for(int i=index;i<length-1;i++){ //刪除元素之後的所有元素前移一位 strArray[i] =strArray[i+1]; } length--; return true; }else{ return false; } } //列出所有元素 public void display(){ for(int i=0;i<length;i++){ System.out.print(strArray[i]+"\t"); } } }
無序數組的優點:插入快,如果知道下標,可以很快的存取
無序數組的缺點:尋找慢,刪除慢,大小固定。
有序數組
所謂的有序數組就是指數組中的元素是按一定規則排列的,其好處就是在根據元素值尋找時可以是使用二分尋找,尋找效率要比無序數組高很多,在資料量很大時更加明顯。當然缺點也顯而易見,當插入一個元素時,首先要判斷該元素應該插入的下標,然後對該下標之後的所有元素後移一位,才能進行插入,這無疑增加了很大的開銷。
因此,有序數組適用於尋找頻繁,而插入、刪除操作較少的情況
有序數組的封裝類如下,為了方便,我們依然假設數組中是沒有重複值的,並且資料是按照由小到大的順序排列的
public class OrderArray { private int [] intArray; private int length = 0; //數組元素個數 //構造方法,傳入數組最大長度 public OrderArray(int max){ intArray = new int [max]; } //用二分尋找法定位某個元素,如果存在返回其下標,不存在則返回-1 public int find(int target){ int lowerBound = 0; //搜尋段最小元素的小標 int upperBound = length-1; //搜尋段最大元素的下標 int curIn; //當前檢測元素的下標 if(upperBound<0){ //如果數組為空白,直接返回-1 return -1; } while(true){ curIn =(lowerBound+upperBound)/2; if(target == intArray[curIn]){ return curIn; }else if(curIn ==lowerBound){ //在當前下標與搜尋段的最小下標重合時,代表搜尋段中只包含1個或2個元素, //如果低位元素和高位元素都不等於目標元素,證明數組中沒有該元素,搜尋結束 if(target !=intArray[upperBound]){ return -1; } }else{//搜尋段中的元素至少有三個,且當前元素不等於目標元素 if(intArray[curIn]< target){ //如果當前元素小於目標元素,則將下一個搜尋段的最小下標置為當前元素的下標 lowerBound =curIn; }else{ //如果當前元素大於目標元素,則將下一個搜尋段的最大下標置為當前元素的下標 upperBound =curIn; } } } } //插入 public void insert(int elem) { int location = 0; //判斷應插入位置的下標 for(;location<length;location++){ if(intArray[location] >elem) break; } //System.out.println(location); //將插入下標之後的所有元素後移一位 for(inti=length;i>location;i--){ intArray[i] = intArray[i-1]; } //插入元素 intArray[location] = elem; length++; } //刪除某個指定的元素值,刪除成功則返回true,否則返回false public boolean delete(int target){ int index = -1; if((index = find(target)) != -1){ for(inti=index;i<length-1;i++){ //刪除元素之後的所有元素前移一位 intArray[i] = intArray[i+1]; } length--; return true; }else{ return false; } } //列出所有元素 public void display(){ for(int i=0;i<length;i++){ System.out.print(intArray[i]+"\t"); } System.out.println(); }}
有序數組最大的優勢就是可以提高尋找元素的效率,在上例中,find方法使用了二分尋找法,該演算法的如下:
這個方法在一開始設定變數lowerBound和upperBound指向數組的第一個和最後一個非空資料項目。通過設定這些變數可以確定尋找的範圍。然後再while迴圈中,當前的下標curIn被設定為這個範圍的中間值
如果curIn就是我們要找的資料項目,則返回下標,如果不是,就要分兩種情況來考慮:如果curIn指向的資料項目比我們要找的資料小,則證明該元素只可能在curIn和upperBound之間,即數組後一半中(數組是從小到大排列的),下輪要從後半段檢索;如果curIn指向的資料項目比我們要找的資料大,則證明該元素只可能在lowerBound和curIn之間,下一輪要在前半段中檢索
按照上面的方法迭代檢索,直到結束
有序數組的優點:尋找效率高
有序數組的缺點:刪除和插入慢,大小固定