順序表與鏈表是很是基本的數據結構,它們能夠被統稱爲線性表。
線性表(Linear List)是由 n(n≥0)個數據元素(結點)a[0],a[1],a[2]…,a[n-1] 組成的有限序列。
順序表和鏈表,是線性表的不一樣存儲結構。它們各自有不一樣的特色和適用範圍。針對它們各自的缺點,也有不少改進的措施。node
順序表通常表現爲數組,使用一組地址連續的存儲單元依次存儲數據元素,如圖 1 所示。它具備以下特色:sql
#include <string.h> struct sqlist { int *items, size, capacity; sqlist():size(0), capacity(4) { // initial capacity = 4 items = new int[capacity]; } void doubleCapacity() { capacity *= 2; int* newItems = new int[capacity]; memcpy(newItems, items, sizeof(int)*size); delete[] items; items = newItems; } void add(int value) { if (size >= capacity) { doubleCapacity(); } items[size++] = value; } };
這個辦法不可避免的會浪費一些內存,由於數組的容量老是倍增的。並且每次擴容的時候,都須要將舊的數據所有複製一份,確定會影響效率。不過實際上,這樣作仍是直接使用鏈表的效率要高,具體緣由會在下一節進行分析。數組
鏈表,相似它的名字,表中的每一個節點都保存有指向下一個節點的指針,全部節點串成一條鏈。根據指針的不一樣,還有單鏈表、雙鏈表和循環鏈表的區分,如圖 2 所示。
數據結構
#include <stdio.h> #include <time.h> struct node { int value; node *next; }; struct llist { node *head; void add(int value) { node *newNode = new node(); newNode->value = value; newNode->next = head; head = newNode; } }; int main() { int size = 100000; sqlist list1; llist list2; long start = clock(); for (int i = 0;i < size;i++) { list1.add(i); } long end = clock(); printf("sequence list: %d\n", end - start); start = clock(); for (int i = 0;i < size;i++) { list2.add(i); } end = clock(); printf("linked list: %d\n", end - start); return 0; }
在個人電腦上,鏈表的耗時大約是順序表的 4~8 倍。會這樣,是由於數組只須要不多的幾回大塊內存分配,而鏈表則須要不少次小塊內存分配,內存分配操做相對是比較慢的,於是大大拖慢了鏈表的速度。這也是爲何會出現內存池。指針
所以,鏈表並不像理論分析的那樣美好,在實際應用中要受不少條件制約,通常狀況下仍是安心用順序表的好。code