前面已經講解了單鏈表,除此以外還有 雙鏈表,循環鏈表和靜態鏈表等,那就讓咱們一塊兒認識鏈表家族中的其餘成員吧算法
此文參考博客: https://blog.csdn.net/daijin888888/article/details/68925248 詳情請移步數組
1、順序存儲結構性能
1.1 存儲方式學習
由於每一個數據元素的類型都相同,因此可使用一位數組來實現。結構代碼以下:spa
//線性表的順序存儲結構 #define MAXSIZE 20;//存儲空間初始分配量爲20 typedef int ElemType;//數據類型爲int type struct { ElemType data[MAXSIZE];//數組存儲數據元素 int length;//線性表長度 }SqList;
這裏能夠看到,順序存儲結構須要三個屬性:.net
1.2 地址計算方法設計
若每一個存儲元素佔用c個存儲希望,那麼線性表中元素的位置能夠由此計算出:3d
LOC(ai) = LOC(ai) + (i-1)*c指針
經過這個公式,可隨時算出線性表中任意位置的地址,使用相同的時間。它的存取時間性能爲O(1),這一特色的存儲結構稱之爲隨機存取結構。code
2、鏈式存儲結構的線性表
2.1 單鏈表
頭指針:鏈表中第一個結點的存儲位置
頭結點:有時爲了便於操做,在單鏈表的第一個結點前附設一個結點,稱爲頭結點。頭結點的數據域能夠不存信息,能夠存線性表的長度等附加信息,頭結點的指針域指向第一個結點的指針。
頭指針和頭結點的區別:
頭指針
頭結點
鏈式存儲結構:
typedef struct Node{ // 線性表的單鏈表存儲結構 ElemType data; struct Node *next; }Node; typedef struct Node *LinkList; // 定義LinkList
這裏講一下,單鏈表的頭插法和尾插法:
頭插法:
1 LinkList CreatList1(LinkList &L){ 2 //從表尾到表頭逆向創建單鏈表L,每次均在頭結點以後插入元素 3 Node *s;int x; 4 L=(LinkList)malloc(sizeof(Node)); //建立頭結點 5 L->next=NULL; //初始爲空鏈表 6 scanf("%d", &x); //輸入結點的值 7 8 while(x!=9999) { //輸入 9999 表示結束 9 s=(Node*)malloc(sizeof(Node) ); //建立新結點 10 s->data=x; 11 s->next=L->next; 12 L->next=s; //將新結點插入表中,L爲頭指針 13 scanf ("%d", &x); 14 }
頭插法是逆序的,接着學習 尾插法
代碼以下:
1 LinkList CreatListRear(LinkList &L){ 2 //從表頭到表尾正向創建單鏈表L,每次均在表尾插入元素 3 int x; // 設元素類型爲整型 4 L=(LinkList)malloc(sizeof(LNode)); 5 LNode *s, *r=L; //r 爲表尾指針 6 scanf ("%d", &x); //輸入結點的值 7 8 while (x!=9999) { //輸入 9999 表示結束 9 s=(LNode *)malloc(sizeof(LNode)); 10 s->data=x; 11 r->next=s; 12 r=s; //r指向新的表尾結點 13 scanf ("%d", &x); 14 } 15 16 r->next = NULL; //尾結點指針置空 17 return L; 18 }
尾插法最後的輸出序列是正序的
單鏈表結構與順序存儲結構優缺點
2.2 靜態鏈表(鏈表的遊標實現)
用數組描述的鏈表就作靜態鏈表。(這個就跟上一節講解的模擬單鏈表很相似)
靜態鏈表的優缺點:
總的說,靜態鏈表是爲了給沒有指針的高級語言設計的一種實現單鏈表能力的方法。雖使用較少,但思考方式比較巧妙,思想值得借鑑。
3.3 雙鏈表
雙鏈表中的每一個節點有兩個子節點,一個指向它的前驅,一個指向它的後繼。
採用尾插法創建雙鏈表以下:
1 void CreateDlistR (DLNode *&L, int a[], int n){ 2 DLNode*s,*r; 3 inti; 4 L = (DLNode*)malloc(sizeof(DLNode)); 5 L->next = NULL; 6 7 //和單鏈表同樣r始終指向終端結點,開始頭結點也是尾結點 8 r = L; 9 10 for(i = 1; i< = n; i++){ 11 //建立新結點s->data = a[i]; 12 s = (DLNode*)malloc(sizeof(DLNode)); 13 14 /*下邊3句將s插入在L的尾部而且r指向s,s->prior = r;這一句是和創建單鏈表不一樣的地方。 */ 15 r->next = s; 16 s->prior = r; 17 r = s; 18 } 19 r->next = NULL; 20 }
3.4 循環鏈表
3.4.1 循環單鏈表
只要將單鏈表的最後一個指針域(空指針)指向鏈表中第一個結點便可(這裏之因此說第一個結點而不說是頭結點是由於,若是循環單鏈表是帶頭結點的則最後一個結點的指針域要指向頭結點;若是循環單鏈表不帶頭結點,則最後一個指針域要指向開始結點)。
帶頭結點的循環單鏈表當head等於head->next時鏈表爲空;
不帶頭結點的循環單鏈表當head等於null時鏈表爲空。
3.4.2 循環雙鏈表
循環雙鏈表的構造源自雙鏈表,即將終端結點的nnext指針指向鏈表中第一個結點,將鏈表中第一個結點的prior指針指向終端結點。
帶頭結點的循環雙鏈表當head->next和heaad->prior兩個指針都等於head時鏈表爲空。
不帶頭結點的循環雙鏈表當head等於null的時候爲空。
循環鏈表的算法操做
循環單鏈表和循環雙鏈表由對應的單鏈表和雙鏈表改造而來,秩序在終端節點和頭節點間創建聯繫便可。
循環單鏈表終端結點的next結點指針指向表頭結點;循環雙鏈表終端結點的next指針指向表頭結點,頭結點的prior指針指向表尾結點。
若是p指針沿着循環鏈表行走,判斷p走到表尾結點的條件是p->next == head
。循環鏈表的各類操做均與非循環鏈表相似。