用數組描述的鏈表,稱爲靜態鏈表。
數組元素由兩個數據域data和cur組成:data存放數據元素;cur相當於單鏈表中的next指針,稱爲遊標。
某一靜態鏈表結構如圖所示(遊標存放內容可參考程序中的說明1):
靜態鏈表的優缺點:
靜態鏈表實現程序:
/**
* 說明:
* 1.數組第一個元素的cur爲備用鏈表第一個結點下標,
* 數組最後一個元素的cur爲第一個有數據的元素的下標,相當於頭結點
* 最後一個有值元素的 cur爲0
* 2.插入刪除操作時,獲取第i-1個元素的 下標時,應注意i-1=0的情況
* 3.註釋中的“位置”指的是在鏈表中的位置,“下標”代表數組中的下標,勿搞混
* 4.程序關鍵:獲取下標,在數組層面上操作
* 5.程序中主要寫了插入刪除操作,其餘基本操作與之前文章類似
*
* 問題:
* 1.泛型數組的建立
* 2.書中P73的if(space[0].cur)和P74的if(j)是屬於判斷什麼?
*
*/
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;
}
}
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;
}