1. 順序表的原理以及實現:
1.1 什么是順序表:
順序表是在計算機內存中以數組的形式保存的線性表,順序表是簡單的一種線性結構,邏輯上相鄰的數據在計算機內的存儲位置也是相鄰的,可以快速定位第幾個元素,中間不允許有空值,插入、刪除時需要移動大量元素。
1.2 什么是線性表:
線性表是從邏輯結構的角度來說的,除了頭和尾之外,它的每一個元素都只有一個前驅元素和一個后驅元素。各種隊列(單向、雙向、循環隊列),棧等都是線性表的不同例子。而本文題目的 順序表 也是線性表的一種。
1.3 順序表與鏈表的區別:
首先,順序表與鏈表均屬於線性表,只是在邏輯結構和存儲方式上有所不同。
順序表:線性表采用順序存儲的方式存儲就稱之為順序表,順序表是將表中的結點依次存放在計算機內存中一組地址連續的存儲單元中。
鏈表: 線性表采用指針鏈接的方式存儲就稱之為鏈表。
1.4 線性表與數組的區別:
線性表是從邏輯結構的角度來說的,而數組是從物理存貯的角度來說的,線性表可以用數組存貯也可以用鏈表來存貯。同樣的隊列和棧也可以用數組和鏈表存貯,各有利弊。根據具體情況靈活選擇。
在C語言中,數組長度不可變,線性表長度是動態可變的。
1.5 順序表的三個要素:
- 用elems 記錄存儲位置的基地址
- 分配一段連續的存儲空間size
- 用length 記錄實際的元素個數,即順序表的長度
結構體定義
#define MAX_SIZE 100 struct _SqList { ElemType *elems; // 順序表的基地址 int length; // 順序表的長度 int size; // 順序表總的空間大小 }
順序表的初始化
1 #define MAX_SIZE 100 2 typedef struct 3 { 4 int* elems; // 順序表的基地址 5 int length; // 順序表的長度 6 int size; // 順序表的空間 7 }SqList; 8 9 bool initList(SqList& L) //構造一個空的順序表L 10 { 11 L.elems = new int[MAX_SIZE]; //為順序表分配Maxsize 個空間 12 if (!L.elems) return false; //存儲分配失敗 13 L.length = 0; //空表長度為0 14 L.size = MAX_SIZE; 15 return true; 16 }
2. 順序表添加元素:
1 bool listAppend(SqList &L, int e) 2 { 3 if(L.length==MAX_SIZE) return false; //存儲空間已滿 4 L.elems[L.length] = e; 5 L.length++; //表長增1 6 return true; 7 }
3. 順序表插入元素
1 bool listInsert(SqList& L, int i, int e) 2 { 3 if (i < 0 || i >= L.length)return false; //i 值不合法 4 if (L.length == MAX_SIZE) return false; //存儲空間已滿 5 6 for (int j = L.length - 1; j >= i; j--) 7 { 8 L.elems[j + 1] = L.elems[j]; //從最后一個元素開始后移,直到第i 個元 素后移 9 } 10 11 L.elems[i] = e; //將新元素e 放入第i 個位置 12 L.length++; //表長增1 13 14 return true; 15 }
4. 順序表刪除元素
1 bool listDelete(SqList& L, int i) 2 { 3 if (i < 0 || i >= L.length) return false; //不合法 4 if (i == L.length - 1) //刪除最后一個元素,直接刪除 5 { 6 L.length--; 7 return true; 8 } 9 for (int j = i; j < L.length - 1; j++) 10 { 11 L.elems[j] = L.elems[j + 1]; //被刪除元素之后的元素前移 12 } 13 L.length--; 14 15 return true; 16 }
5. 順序表銷毀
1 void destroyList(SqList& L) 2 { 3 if (L.elems) delete[]L.elems; //釋放存儲空間 4 L.length = 0; 5 L.size = 0; 6 }
6. 完整實現
1 #include <iostream> 2 3 using namespace std; 4 #define MAX_SIZE 100 5 6 typedef struct 7 { 8 int* elems; // 順序表的基地址 9 int length; // 順序表的長度 10 int size; // 順序表的空間 11 }SqList; 12 13 bool initList(SqList& L) //構造一個空的順序表L 14 { 15 L.elems = new int[MAX_SIZE]; //為順序表分配Maxsize 個空間 16 if (!L.elems) return false; //存儲分配失敗 17 L.length = 0; //空表長度為0 18 L.size = MAX_SIZE; 19 return true; 20 } 21 22 /* 23 bool getElem(SqList &L,int i,int &e) 24 { 25 //防御性檢查 26 if (i<1||i>L.length) return false; 27 e=L.elems[i-1]; //第i-1 的單元存儲着第i 個數據 28 return true; 29 } 30 */ 31 32 bool listAppend(SqList& L, int e) 33 { 34 if (L.length == MAX_SIZE) return false; //存儲空間已8滿979438401111 35 L.elems[L.length] = e; 36 L.length++; //表長增1 37 return true; 38 } 39 40 bool listInsert(SqList & L, int i, int e) 41 { 42 if (i < 0 || i >= L.length)return false; //i 值不合法 43 if (L.length == MAX_SIZE) return false; //存儲空間已滿 44 for (int j = L.length - 1; j >= i; j--) 45 { 46 L.elems[j + 1] = L.elems[j]; //從最后一個元素開始后移,直到第i 個元 素后移 47 } 48 L.elems[i] = e; //將新元素e 放入第i 個位置 49 L.length++; //表長增1 50 return true; 51 } 52 53 bool listDelete(SqList & L, int i) 54 { 55 if (i < 0 || i >= L.length) return false; //不合法 56 if (i == L.length - 1) //刪除最后一個元素,直接刪除 57 { 58 L.length--; 59 return true; 60 } 61 for (int j = i; j < L.length - 1; j++) 62 { 63 L.elems[j] = L.elems[j + 1]; //被刪除元素之后的元素前移 64 } 65 L.length--; 66 return true; 67 } 68 69 void listPrint(SqList & L) 70 { 71 cout << "順序表元素size: " << L.size << ", 已保存元素個數length: " << L.length << endl; 72 for (int j = 0; j <= L.length - 1; j++) 73 { 74 cout << L.elems[j] << " "; 75 } 76 cout << endl; 77 } 78 79 void destroyList(SqList & L) 80 { 81 if (L.elems) delete[]L.elems;//釋放存儲空間 82 L.length = 0; 83 L.size = 0; 84 } 85 86 int main() 87 { 88 SqList list; 89 int i, e; 90 91 cout << "順序表初始化..." << endl; 92 //1. 初始化 93 if (initList(list)) { 94 cout << "順序表初始化成功!" << endl; 95 } 96 97 //2. 添加元素 98 int count = 0; 99 cout << "請輸入要添加的元素個數:"; 100 cin >> count; 101 for (int i = 0; i < count; i++) { 102 cout << "\n 請輸入要添加元素e:"; 103 cin >> e; 104 if (listAppend(list, e)) { 105 cout << "添加成功!" << endl; 106 } 107 else { 108 cout << "添加失敗!" << endl; 109 } 110 } 111 112 listPrint(list); 113 114 //3. 插入元素 115 cout << "請輸入要插入的位置和要插入的數據元素e:"; 116 cin >> i >> e; 117 if (listInsert(list, i, e)) { 118 cout << "插入成功!" << endl; 119 } 120 else { 121 cout << "插入失敗!" << endl; 122 } 123 124 listPrint(list); 125 126 //4. 刪除元素 127 cout << "請輸入要刪除的位置i:"; 128 cin >> i; 129 if (listDelete(list, i)) { 130 cout << " 刪除成功!" << endl; 131 } 132 else { 133 cout << "刪除失敗!" << endl; 134 } 135 136 listPrint(list); 137 138 //5. 銷毀 139 cout << "順序表銷毀..." << endl; 140 destroyList(list); 141 system("pause"); 142 return 0; 143 }
7. 企業級應用案例
高並發WEB 服務器中順序表的應用高性能的web 服務器Squid 每秒可處理上萬並發的請求,從網絡連接到服務器的客戶端與服務器端在交互時會保持一種會話(和電話通話的場景類似)。服務器端為了管理好所有的客戶端連接,給每個連接都編了一個唯一的整數編號,叫做文件句柄,簡稱fd.
為了防止某些惡意連接消耗系統資源,當某個客戶端連接超時(在設定的一定時間內沒有發送數據)時,服務器就需要關閉這些客戶端的連接.
具體實現方案:
1. 當有新的請求連到服務器時,如果經過服務器頻率限制模塊判斷,貌似惡意連接,則使用順序表來保存此連接的超時數據,超時值使用時間戳來表示,時間戳是指格林威治時間1970 年01 月01 日00 時00 分00 秒(相當於北京時間1970 年01 月01 日08 時00 分00 秒)起至現在的總秒數,其結構體定義如下:
1 typedef struct 2 { 3 int fd; 4 time_t timeout; // 使用超時時刻的時間戳表示 5 }ConnTimeout;
2. 服務器程序每隔一秒鍾掃描一次所有的連接,檢查是否超時,如果存在超時的連接,就關閉連接,結束服務,同時將順序表中的記錄清除!
======================================================================================================================