1、定義
用數組描述的鏈表,即稱爲靜態鏈表。
在C語言中,靜態鏈表的表現形式即爲結構體數組,結構體變量包括數據域data和遊標CUR。(這裏的定義來自於百度百科)java
2、優勢
(1)這種存儲結構,仍須要預先分配一個較大的空間,但在做爲線性表的插入和刪除操做時不需移動元素,僅需修改指針,故仍具備鏈式存儲結構的主要優勢。
(2)假若有如上的靜態鏈表S中存儲這線性表(a,b,c,d,f,g,h,i),Maxsize=11,如圖所示,要在第四個元素後插入元素e,方法是:先在當前表尾加入一個元素e,即:S[9].data = e;而後修改第四個元素的遊標域,將e插入到鏈表中,即:S[9].cursor = S[4].cursor; S[4].cursor = 9;,接着,若要刪除第7個元素h,則先順着遊標鏈經過計數找到第7個元素存儲位置6,刪除的具體作法是令S[6].cursor = S[7].cursor。數組
3、原理圖數據結構
例如一組數據以下:函數
(ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG)spa
1 /** 2 * 靜態鏈表的長度 3 * @return 4 */ 5 public int length(){ 6 return size-1; 7 }
由於有個空表頭,因此長度爲size-1;3d
1 /** 2 * 靜態鏈表的初始化 3 */ 4 public StaticLinkList(){ 5 linkList = new Element[DEFAULT_SIZE]; 6 for (int i = 0; i < linkList.length; i++) { 7 linkList[i] = new Element(); 8 linkList[i].data = -1; 9 linkList[i].cur = i+1; 10 } 11 //當前空閒節點從1開始,由於第0個節點設置成了頭結點,設置爲空,不 12 //存儲數據 13 currentFree = 1; 14 }
這裏是不指定鏈表大小的鏈表初始化,默認長度爲DEFAULT_SIZE,第8行爲鏈表數據初始化,第9行初始化遊標cur。指針
1 /** 2 * 給鏈表添加數據,每當鏈表滿了就給鏈表添加額外的空間 3 * @param data 4 */ 5 public void add(int data){ 6 if(size<linkList.length){ 7 linkList[currentFree].data = data; 8 currentFree = linkList[currentFree].cur; 9 size++; 10 }else{//鏈表已滿,給鏈表添加空間 11 addLinkSpace(); 12 linkList[currentFree].data = data; 13 currentFree = linkList[currentFree].cur; 14 size++; 15 } 16 }
這個函數是給靜態鏈表添加數據,第6行判斷鏈表是否已滿,currentFree是指向當前空閒位置,第7行是將要添加的數據添加到空閒位置上,第8行currentFree指向下一個空閒位置,第9行鏈表實際長度加1,第11行,若是鏈表已滿,則給鏈表添加空間(addLinkSpace())。code
1 /** 2 * 獲得索引指定的數據 3 * @param index 4 * @return 5 */ 6 public int get(int index){ 7 if(index>size-1&&index<0) 8 throw new IndexOutOfBoundsException("數組越界,索引不合法"); 9 else{ 10 //這裏index+1也是由於多了一個空的頭節點 11 return linkList[index+1].data; 12 } 13 }
第11行index+1是由於鏈表的第一位爲空,不取到第一位。blog
1 /** 2 * 刪除指定位置的節點 3 * @param index 4 */ 5 public void delete(int index){ 6 7 index = index+1; 8 if(index<1||index>=size){ 9 System.out.println("超出鏈表長度"); 10 }else if(index == size-1){ 11 size--; 12 linkList = (Element[]) getTrueIndex(linkList,size); 13 }else{ 14 int i = 0; 15 while(index!=linkList[i].cur){ 16 i++; 17 } 18 int j = 0; 19 while(currentFree!=linkList[j].cur){ 20 j++; 21 } 22 linkList[i].cur = linkList[index].cur; 23 linkList[j].cur = index; 24 linkList[index].cur = currentFree; 25 currentFree = index; 26 size--; 27 linkList = (Element[]) getTrueIndex(linkList,size); 28 } 29 }
第7行也是由於鏈表頭結點爲空。第10行是指,若是刪除鏈表的最後一位,則執行下面的操做。第12行是將鏈表按照邏輯順序從新排列,是爲了顯示。第14-17行是爲了找到指向index的遊標,若是沒有12行,則指向index的遊標不必定是index-1,由於物理位置連續的,邏輯位置不必定連續。18-21行是爲了找到指向當前空閒位置的遊標,理由同上。22行是將原指向index的遊標指向原index的遊標指向的位置,23行是將原指向當前空閒位置的遊標指向index,代表index爲空閒,24行是將index的遊標指向原當前空閒位置,25行是將當前空閒位置指向index。其餘的都是差很少的,還有幾個函數就不一一介紹了。排序
4、完整代碼示例
4.1 StaticLinkList.java
package com.yds.list; /** * 由於靜態鏈表實質上是一維數組的存儲方式,因此它在物理位置上的存儲 * 是順序的,但它是用遊標來指向下一個數據的,因此根據它的下標來獲取數據 * 和按照遊標的指向來獲取數據是不一樣的,這裏設置該鏈表的頭結點爲空 * @author Administrator * */ public class StaticLinkList { private Element[] linkList = null; // private Element[] linkList1 = null; private int DEFAULT_SIZE = 4;//默認存儲大小 private int currentFree = 0;//指向當前空閒位置 private int size = 1; class Element{ int data; int cur; } /** * 靜態鏈表的長度 * @return */ public int length(){ return size-1; } /** * 靜態鏈表的初始化 */ public StaticLinkList(){ linkList = new Element[DEFAULT_SIZE]; for (int i = 0; i < linkList.length; i++) { linkList[i] = new Element(); linkList[i].data = -1; linkList[i].cur = i+1; } //當前空閒節點從1開始,由於第0個節點設置成了頭結點,設置爲空,不 //存儲數據 currentFree = 1; } /** * 給鏈表添加數據,每當鏈表滿了就給鏈表添加額外的空間 * @param data */ public void add(int data){ if(size<linkList.length){ linkList[currentFree].data = data; currentFree = linkList[currentFree].cur; size++; }else{//鏈表已滿,給鏈表添加空間 addLinkSpace(); linkList[currentFree].data = data; currentFree = linkList[currentFree].cur; size++; } } /** * 獲得索引指定的數據 * @param index * @return */ public int get(int index){ if(index>size-1&&index<0) throw new IndexOutOfBoundsException("數組越界,索引不合法"); else{ //這裏index+1也是由於多了一個空的頭節點 return linkList[index+1].data; } } /** * 刪除指定位置的節點 * @param index */ public void delete(int index){ index = index+1; if(index<1||index>=size){ System.out.println("超出鏈表長度"); }else if(index == size-1){ size--; linkList = (Element[]) getTrueIndex(linkList,size); }else{ int i = 0; while(index!=linkList[i].cur){ i++; } int j = 0; while(currentFree!=linkList[j].cur){ j++; } linkList[i].cur = linkList[index].cur; linkList[j].cur = index; linkList[index].cur = currentFree; currentFree = index; size--; linkList = (Element[]) getTrueIndex(linkList,size); } } /** * 增長鏈表空間 */ public void addLinkSpace(){ DEFAULT_SIZE+=8; Element[] link = linkList; linkList = new Element[DEFAULT_SIZE]; System.arraycopy(link, 0, linkList, 0, link.length); for (int i = link.length; i < DEFAULT_SIZE; i++) { linkList[i] = new Element(); linkList[i].data = -1; linkList[i].cur = i+1; } currentFree = link.length; } /** * 根據指定的位置插入數據 * @param index * @param data */ public void insert(int index,int data){ //這裏加1的緣由是由於鏈表的第0位爲空節點,這裏設置的頭節點爲空 index = index + 1; if(size<linkList.length){ if(index>size&&index<0) System.out.println("數組越界,超出數組長度"); else if(index == size){ linkList[currentFree].data = data; currentFree = linkList[currentFree].cur; size++; }else{ /******未按邏輯順序排序而插入數據的寫法,由於未排序,則當前索引的上個節點的索引不必定是當前索引減1****/ int i = 0; while(index!=linkList[i].cur){ i++; } int j = 0; while(currentFree!=linkList[j].cur){ j++; } linkList[i].cur = currentFree; linkList[j].cur = linkList[currentFree].cur; linkList[currentFree].data = data; linkList[currentFree].cur = index; currentFree = linkList[j].cur; size++; //每次插入後將鏈表按邏輯順序從新排序,是爲了方便輸出查看。 linkList = (Element[]) getTrueIndex(linkList,size); } }else{ addLinkSpace(); insert(index, data); } } /** * 按照邏輯順序從新排列 * @param link * @return */ public Object getTrueIndex(Element[] link,int size){ Element[] linkList1 = new Element[linkList.length]; int k =0; for (int i = 0; i < linkList.length; i++) { linkList1[i] = new Element(); linkList1[i].data = link[k].data; k = link[k].cur; linkList1[i].cur = i+1; } //插入時,currentFree確定是最後一個了,但刪除後,currentFree就不必定是最後一位了 currentFree = size; return linkList1; } }
4.2 JavaMain.java
package com.yds.list; public class JavaMain { public static void main(String[] args) { // TODO Auto-generated method stub StaticLinkList listA = new StaticLinkList(); int la[]={ 2,3,5,8,9,6,7 }; for (int i = 0; i < la.length; i++) { listA.add(la[i]); } listA.delete(6); listA.delete(0); listA.insert(3, 88); listA.insert(3, 78); for (int i = 0; i < listA.length(); i++) { System.out.println(listA.get(i)); } } }
5、結果截圖