本文根據《大話數據結構》一書,實現了Java版的靜態鏈表。java
用數組描述的鏈表,稱爲靜態鏈表。node
數組元素由兩個數據域data和cur組成:data存放數據元素;cur至關於單鏈表中的next指針,稱爲遊標。數組
某一靜態鏈表結構如圖所示(遊標存放內容可參考程序中的說明1):數據結構
靜態鏈表的優缺點:ide
靜態鏈表實現程序:測試
package StaticLinkList; /** * 說明: * 1.數組第一個元素的cur爲備用鏈表第一個結點下標, * 數組最後一個元素的cur爲第一個有數據的元素的下標,至關於頭結點 * 最後一個有值元素的 cur爲0 * 2.插入刪除操做時,獲取第i-1個元素的 下標時,應注意i-1=0的狀況 * 3.註釋中的「位置」指的是在鏈表中的位置,「下標」表明數組中的下標,勿搞混 * 4.程序關鍵:獲取下標,在數組層面上操做 * 5.程序中主要寫了插入刪除操做,其他基本操做與以前文章相似 * * 問題: * 1.泛型數組的創建 * 2.書中P73的if(space[0].cur)和P74的if(j)是屬於判斷什麼? * * @author Yongh */ public class StaticLinkList<E> { private SNode<E>[] nodes; private int maxSize; public StaticLinkList(){ this(1000); } public StaticLinkList(int maxSize){ this.maxSize=maxSize; nodes=new SNode[this.maxSize];//泛型的數組創建彷佛有些問題 for(int i=0;i<this.maxSize-1;i++) { nodes[i]=new SNode<E>(null, i+1); } nodes[maxSize-1]=new SNode<E>(null, 0); } class SNode<E> { E data; int cur; public SNode(E data,int cur){ this.data=data; this.cur=cur; } } /** * 獲取第i個元素的下標 */ public int getIndex(int i){ if(i<1||i>this.getLength()) throw new RuntimeException("查找位置錯誤!"); int k=nodes[maxSize-1].cur; for (int j=1;j<i;j++) k=nodes[k].cur; return k; } /** * 獲取第i個元素 */ public SNode<E> getElement(int i){ return nodes[getIndex(i)]; } /** * 返回可分配結點下標 */ public int malloc_sll() { int i= nodes[0].cur; nodes[0].cur=nodes[i].cur;//第i個份量要拿來用了,因此指向下一個份量 //注意,不是nodes[0].cur=nodes[0].cur+1,下一個份量不必定就是下標加一; return i; } /** * 插入操做,i表明第i個位置,而不是下標 * 注意插入到第一個位置的特殊性 */ public void listInsert(int i,E e) { if(i<1||i>this.getLength()+1) throw new RuntimeException("插入位置錯誤!"); if(getLength()==maxSize-2) throw new RuntimeException("表已滿,沒法插入!"); int j=this.malloc_sll(); nodes[j].data=e; int p; ////第i-1個元素的下標 if(i==1) { p=maxSize-1; }else { p=getIndex(i-1); } nodes[j].cur=nodes[p].cur; nodes[p].cur=j; } /** * 刪除第i個位置的結點 */ public SNode<E> listDelete(int i) { if(i<1||i>getLength()) throw new RuntimeException("刪除位置錯誤!"); int m= getIndex(i); int p; //第i-1個元素的下標 if(i==1) { p=maxSize-1; }else { p=getIndex(i-1); } nodes[p].cur=nodes[m].cur; free_sll(m); return nodes[m]; } /** * 將下標爲i元素回收到備用鏈表中 */ public void free_sll(int i) { nodes[i].cur=nodes[0].cur; nodes[0].cur=i; } /** * 返回靜態鏈表的長度 */ public int getLength() { int length=0; int i=nodes[maxSize-1].cur; while(i!=0) { i=nodes[i].cur; length++; } return length; } }
測試代碼:this
package StaticLinkList; public class StaticLinkListTest { public static void main(String[] args) { StaticLinkList<Student> students =new StaticLinkList<Student>(); System.out.println("——————————插入1到5,並讀取內容——————————"); Student[] stus= {new Student("小A",11),new Student("小B",12),new Student("小C",13), new Student("小D",14),new Student("小E",151)}; for(int i=1;i<=5;i++) students.listInsert(i, stus[i-1]); System.out.println("表長:"+students .getLength()); Student stu; for(int i=1;i<=5;i++) { stu=students .getElement(i).data; System.out.println("第"+i+"個位置爲:"+stu.name); } System.out.println("——————————刪除小B、小E——————————"); stu=students .listDelete(2).data; System.out.println("已刪除:"+stu.name); stu=students .listDelete(4).data; System.out.println("已刪除:"+stu.name); System.out.println("當前表長:"+students .getLength()); for(int i=1;i<=students .getLength();i++) { stu=students .getElement(i).data; System.out.println("第"+i+"個位置爲:"+stu.name); } System.out.println("表長:"+students.getLength()); } } class Student{ public Student(String name, int age) { this.name=name; this.age=age; } String name; int age; }
——————————插入1到5,並讀取內容—————————— 表長:5 第1個位置爲:小A 第2個位置爲:小B 第3個位置爲:小C 第4個位置爲:小D 第5個位置爲:小E ——————————刪除小B、小E—————————— 已刪除:小B 已刪除:小E 當前表長:3 第1個位置爲:小A 第2個位置爲:小C 第3個位置爲:小D 表長:3