1. 程式人生 > >資料結構與演算法學習總結-線性表的順序儲存與實現

資料結構與演算法學習總結-線性表的順序儲存與實現

  線性表的順序儲存是用一組地址連續的儲存單元一次儲存線性表的資料元素。

1.線性表的順序儲存

  假設線性表的每個資料元素需佔用K個儲存單元,並以元素所佔的第一個儲存單元的地址作為資料元素的儲存地址。則線性表中序號為i的資料元素的儲存地址LOC(ai)與序號為i+1的資料元素的儲存地址LOC(ai+1)之間的關係為:
  LOC(ai+1)=LOC(ai)+K
  通常來說,線性表的i號元素的儲存地址為:
  LOC(ai+1)=LOC(a0)+i×K
  其中LOC(a0)為0號元素的儲存地址,通常稱為線性表的起始地址。
  線性表的這種機內表示稱作線性表的順序儲存。它的特點是,以資料元素在機記憶體儲地址相鄰來表示線性表中資料元素之間的邏輯關機。每一個數據元素的儲存地址都和線性表的起始地址相差一個與資料據元素線上性表中的序號成正比的常數。由此,只要確定了線性表的起始地址,線性表中的任何一個數據元素都可以隨機存取,因此線性表的順序儲存結構時一種隨機的儲存結構。如圖所示:

線性表的順序儲存
線性表的順序儲存

  由於高階語言中的陣列具有隨機儲存的特性,因此在抽象資料型別的實現中都是使用陣列來描述資料結構的順序儲存結構。線性表中的資料元素在一次存放的陣列中的時候,線性表中序號為i的資料元素對應的陣列下標頁為i,即資料元素線上性表中的序號與資料元素在陣列中的下標相同。
  如果線性表中的資料元素是物件是,陣列存放的是物件的引用,即線性表中所有資料元素的物件引用是存放在一組連續的地址空間中。
陣列儲存物件引用
陣列儲存物件引用

2.線性表的操作

  由於線性表的長度可變,不同的問題所需的最大長度不同,那麼線上性表的具體視線中我們是使用動態擴充套件陣列大小的方式來完成線性表長度的不同要求的。
  在使用陣列實現線性表的操作中,經常會遇到在陣列中進行資料元素的查詢、新增、刪除等操作。
  查詢:

在陣列中進行查詢,最簡單的方法就是順序查詢,平均時間複雜度θ(n).
  新增:在陣列中新增資料元素,通常是在陣列中下標為i(0≤i≤n)的位置新增資料元素,而將原來下標從i開始的陣列中所有後續元素依次後移,如圖所示:

在陣列下標i處插入元素e
在陣列下標i處插入元素e

  程式碼:
for(int j = n;j > i;j--){
a[j] = a[j - 1];
}
a[i] = e;

  時間複雜度:θ(n)。
  刪除:與新增相似。

3.線性表的陣列實現

public class ListArray implements List{
    //陣列的預設大小
    private final
int LEN = 8; //資料元素比較策略 private Strategy strategy; //線性表中的資料元素的個數 private int size; //資料元素陣列 private Object[] elements; //構造方法 public ListArray(){ this(new DefaultStrategy()); } public ListArray(Strategy strategy){ this.strategy = strategy; size = 0; elements = new Object[LEN]; } //返回線性表的大小,即資料元素的個數。 public int getSize(){ return size; } //如果線性表為空返回true,否則返回false。 public boolean isEmpty(){ return size = 0; } //判斷線性表是否包含資料元素e public boolean contaions(Object e){ for(int i = 0;i < size;i++){ if(strategy.equal(e,elements[i])){ return true; } return false; } } //返回資料元素e線上性表中的序號 public int indexOf(Object e){ for(int i = 0;i < size;i++){ if(strategy.equal(e,elements[i])){ return i; } return -1; } } //將資料元素e插入到線性表中i號位置 public void insert(int i,Object e)throws OutOfBoundaryException{ if(i < 0||i > size){ throw new OutOfBoundaryException(“錯誤,指定的插入序號越界。”) } if(size ≥ elements.length){ expandSpace(); } for(int j = size;j > i;j--){ elements[j] = elements[j-1]; } elements[i] = e; size++; return; } public void expandSpace(){ Object[] a = new Object[elements.length*2]; for(int i = 0;i < elements.length;i++){ a[i] = elements[i]; } elements = a; } //將資料元素e插入到元素obj之前 public boolean insertBefore(Object obj,Object e){ int i = indexOf(obj); if(i < 0){ insert(i,e); return false; } return true; } //將資料元素e插入到元素obj之後 public boolean insertAfter(Object obj,Object e){ int i = indexOf(obj); if(i < 0){ insert(i+1,e); return false; } return true; } //刪除線性表中序號為i的元素,並返回之 public Object remove(int i) throws OutOfBoundaryException{ if(i < 0||i > size){ throw new OutOfBoundaryException(“錯誤,指定的刪除序號越界。”) } Object obj = elements[i]; for(int j = i;j < size-1;j++){ elements[j] = elements[j + 1]; } elements[--size] = null; return obj; } //刪除線性表中第一個與e相同的元素 public boolean remove(Object e){ int i = indexOf(e); if(i < 0){ remove(i) return false; } return true; } //替換線性表中序號為i的資料元素為e,返回原資料元素 public Object replace(int i,Object e)throws OutOfBoundaryException{ if(i < 0||i > size){ throw new OutOfBoundaryException(“錯誤,指定的序號越界。”) } Object obj = elements[i]; elements[i] = e; return obj; } //返回線性表中序號為i的資料元素 public Object get(int i)throws OutOfBoundaryException{ if(i < 0||i > size){ throw new OutOfBoundaryException(“錯誤,指定的序號越界。”) } return elements[i]; } }

  說明:在ArrayList類中共有4個成員變數。其中elements陣列以及size用於儲存線性表中的資料元素以及表明線性表中資料元素的個數;而strategy是用來完成線性表中資料元素的比較策略;LEN是elements陣列的初始預設大小,陣列的大小在後續的插入操作中可能會發生變化。