首先我們讓數組的元素都是由兩個數據域組成,data和cur。也就是說,數組的每一個下標都對應一個data和一個cur。
數據域data用來存放數據元素,也就是通常我們要處理的數據;而游標cur相當於單鏈表中的next指針,
存放該元素的后繼在數組中的下標。我們把這種用數組描述的鏈表叫做靜態鏈表。
數組的第一個元素,即下標為0的元素的cur就存放備用鏈表的第一個結點的下標;而數組的最后一個元素的cur
則存放第一個有數值的元素的下標,相當於單鏈表的頭節點作用,當整個鏈表為空時,則為0,表示無指向。如圖3-12-2所示
現在如果我們需要在“乙”和“丁”之間插入一個值為“丙”的元素,只需要將“乙”的cur改為7,表示下一位是“丙”,並將“丙”的cur改為3,表示下一位是丁。
如圖3-12-3所示。
現在如果我們刪除了第一個元素“甲”,表示現在“甲”這個位置空出來了,如果未來有新人要來則優先考慮這里,所以刪除的位置成為第一個優先空位,即首元素的cur為1, 第一個元素位置的cur改為8,而下標為8的位置cur改為9,最后元素位置的cur改為2,如圖3-12-4所示。
示例代碼:(改編自《大話數據結構》)
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
#include<iostream>
using namespace std; #define MAXSIZE 100 typedef int ElemType; /* 線性表的靜態鏈表存儲結構 */ typedef struct Node { ElemType data; int cur; //為0時表示無指向 } StaticLinkList[MAXSIZE]; /* 將一維數組array中各分量鏈成一個備用鏈表,array[0].cur為頭指針,"0"表示空指針 */ bool InitList(StaticLinkList array) { cout << "InitList..." << endl; for (int i = 0; i < MAXSIZE - 2; i++) { array[i].cur = i + 1; }
20; /* 最后一個元素也是不可用的,倒數第二個元素的cur為0 */ array[MAXSIZE - 1].cur = 0; /* 目前靜態鏈表為空,最后一個元素的cur為0 */ return true; } /* 若備用空間鏈表非空,則返回分配的結點下標,否則返回0 */ int Malloc_SLL(StaticLinkList array) { int k = array[0].cur; if (k) array[0].cur = array[k].cur;/* 下一個分量用來做備用 */ return k; } /* 將下標為pos的空閑結點回收到備用鏈表 */ void Free_SLL(StaticLinkList array, int pos) { array[pos].cur = array[0].cur; /* 把第一個元素的cur值賦給要刪除的分量cur */ array[0].cur = pos; /* 把要刪除的分量下標賦值給第一個元素的cur */ } int ListLength(StaticLinkList array) { int i = array[MAXSIZE - 1].cur; int j = 0; while(i) { i = array[i].cur; ++j; } return j; } /* 在array中第pos個元素之前插入新的數據元素Elem */ bool ListInsert(StaticLinkList array, int pos, ElemType Elem) { cout << "Insert List from pos: " << pos << " Item " << Elem << endl; if (pos < 1 || pos > ListLength(array) + 1) return false; int k = MAXSIZE - 1; int i = Malloc_SLL(array); /* 獲得空閑分量的下標 */ if (i) { array[i].data = Elem; for (int l = 1; l <= pos - 1; l++) k = array[k].cur; array[i].cur = array[k].cur;/* 把第pos個元素之前的cur賦值給新元素的cur */ array[k].cur = i;/* 把新元素的下標賦值給第pos個元素之前元素的cur */ return true; } return false; } /* 刪除在array中第pos個數據元素 */ bool ListDelete(StaticLinkList array, int pos) { cout << "Delete List from pos: " << pos << endl; if (pos < 1 || pos > ListLength(array)) return false; int k = MAXSIZE - 1; for (int l = 1; l <= pos - 1; l++) k = array[k].cur; int j = array[k].cur; array[j].cur = array[pos].cur; Free_SLL(array, j); return true; } bool ListTraverse(StaticLinkList array) { cout << "List Traverse : " << endl; int k = MAXSIZE - 1; while (array[k].cur != 0) { k = array[k].cur; cout << array[k].data << ' '; } cout << endl; return true; } int main(void) { StaticLinkList SSL; InitList(SSL); for (int i = 1; i < 5; i++) ListInsert(SSL, i, i); ListTraverse(SSL); ListDelete(SSL, 3); ListTraverse(SSL); cout << "List Length : " << ListLength(SSL) << endl; return 0; } |
輸出為:
靜態鏈表在插入和刪除操作時不需要移動元素,只需要修改游標,從而改進了在順序存儲結構中插入和刪除操作需要移動
大量元素的缺點;但並沒有解決連續分配存儲帶來的表長難以確定的問題;並且失去了順序存儲結構隨機存取的特性。