1.靜態鏈表是在沒有指針的編程語言里對鏈表的一種實現
2.主要是用數組模擬指針
3.在這里,使用結構體使數組的每一個空間可以存儲一個數據元素(date)和一個游標(cur),游標的作用相當於鏈表的指針域,用於記錄下一元素的下標是多少
4.在沒有結構體(typedef)的語言中,也可以使用兩個並行數組實現此功能
此種結構在編程中不一定能用得到,但是這種思想非常巧妙,非常值得我們學習,不多說,直接上代碼,親測可行,有詳細注釋
#include<stdio.h>
#define MAXSIZE 1000 //靜態鏈表最大空間容量 typedef int ElemType; //數據類型
typedef int Status; //返回值類型
#define OK 1 //操作成功返回值
#define ERROR 0 //操作失敗返回值 typedef struct //靜態鏈表的結構體
{ ElemType date; //結點數據
int cur; //結點游標(相當於鏈表中的地址)
}StaticLinkList[MAXSIZE]; //表名
/* 靜態鏈表的初始化 第一個位置space[0]的cur指向第一個沒有數據的位置空間 最后一個位置space[MAXSIZE-1]的cur指向第一個有數據的位置空間,即頭結點 */ Status InitList(StaticLinkList space) { for(int i = 0; i < MAXSIZE-1; i++) //為數組中的每個位置的游標賦值
space[i].cur = i + 1; space[MAXSIZE-1].cur = 0; //使最后一個位置的游標為0
return OK; } /* 模擬鏈表中的malloc函數,在數組中尋找空閑位置空間作為新結點 */
int malloc_SLL(StaticLinkList space) { int i = space[0].cur; //將備用鏈表的第一個結點位置賦值給i
if(space[0].cur) //如果space[0].cur不是0,即備用鏈表非空
space[0].cur = space[i].cur; //將備用鏈表的下一個空閑位置賦值給space[0]
return i; } /*獲得鏈表的長度*/
int ListLength(StaticLinkList L) { int i, l; l = 0; //記錄鏈表長度
i = MAXSIZE - 1; //獲得頭結點下標
i = L[i].cur; //獲得頭結點位置
while(i) //如果此下標 != 0
{ l++; //長度加1
i = L[i].cur; //下標后移
} return l; //返回長度l
} /* 靜態鏈表的插入操作 */ Status InsertLinkList(StaticLinkList L, int i, ElemType e) { int j ,k, l; k = MAXSIZE-1; //獲取頭結點的下標
if(i < 1 || i > ListLength(L)+1) //判斷要插入的位置是否合理
return ERROR; j = malloc_SLL(L); //獲得備用鏈表中的第一個位置下標
if(j) //如果此下標不是0,說明還有空間可用
{ L[j].date = e; //將此下標對應位置的數據域賦值為e
for(l = 1; l < i; l++) //遍歷鏈表,尋找i位置之前的結點
k = L[k].cur; //獲得此結點的游標
L[j].cur = L[k].cur; //新結點的游標等於i-1位置的游標
L[k].cur = j; //i-1位置的游標等於新結點的游標
return OK; //操作成功
} return ERROR; //操作失敗
} /*模擬free()函數,將刪除的結點空間加入備用空間*/
void free_SSL(StaticLinkList space, int i) { space[i].cur = space[0].cur; //刪除位置的游標等於0位置的游標
space[0].cur = i; //0位置的游標等於當前結點
} /*靜態鏈表的刪除操作*/ Status DelLinkList(StaticLinkList L, int i) { int j, k; if(i < 1 || i > ListLength(L)+1) //判斷刪除的位置是否合理
return ERROR; k = MAXSIZE - 1; //獲得頭結點的游標
for(j = 1; j < i; j++) //尋找i位置
k = L[k].cur; //游標后移
j = L[k].cur; //將要刪除的位置下標賦值給j
L[k].cur = L[j].cur; //使刪除結點的前一結點的游標指向刪除結點的游標
free_SSL(L, j); //釋放刪除的結點
return OK; } /*靜態鏈表的遍歷操作*/
void PrintLinkList(StaticLinkList L) { int i; int j = MAXSIZE - 1; //獲得數組最后一個位置的下標
j = L[j].cur; //獲得此下標的游標值,即頭結點的下標 // printf("長度為%d\n",ListLength(L));
for(i = 1; i <= ListLength(L); i++) //遍歷此表
{ printf("第%d個結點的數據是:%d\n", i, L[j].date); //輸出每個結點的數據
j = L[j].cur; //獲得下一結點的游標
} } void main() { StaticLinkList L; //創建鏈表L
int i, e; //i為元素位置,e為元素內容
while(true) { printf("請選擇對靜態鏈表的操作:\n"); printf("1.初始化\n"); printf("2.插入\n"); printf("3.刪除\n"); printf("4.輸出\n"); printf("5.退出\n"); int a; scanf("%d", &a); switch(a) { case 1: if(InitList(L)) printf("初始化成功\n"); else printf("初始化失敗\n"); break; case 2: printf("請輸入需要插入的位置:"); scanf("%d", &i); printf("請輸入需要插入的元素:"); scanf("%d", &e); if(InsertLinkList(L, i, e)) printf("插入成功\n"); else printf("插入失敗\n"); break; case 3: printf("請輸入需要刪除的位置:"); scanf("%d", &i); if(DelLinkList(L, i)) printf("刪除成功\n"); else printf("刪除失敗\n"); break; case 4: PrintLinkList(L); break; case 5: return; default: printf("選擇錯誤\n"); break; } } }
