當鏈表的每個結點只包含一個指針域時,我們稱此鏈表為單鏈表。
關於單鏈表的存取,有時候我們在單鏈表的第一個結點(有效元素)之前附設一個結點,稱之為頭結點;指向頭結點的指針,稱之為頭指針;對單鏈表的存取必須從頭指針開始進行,由於單鏈表的最后一個數據元素沒有直接后繼,則指針為NULL。
對於頭結點,數據域可以不存儲任何信息,也可存儲如鏈表長度等附加信息。
下面是帶頭結點的單鏈表與空表的比較圖。
頭指針與頭結點不同,頭結點即第一個結點,頭指針是指向第一個結點的指針。鏈表中可以沒有頭結點,但不能沒有頭指針。
關於頭指針:
- 在線性表的鏈式存儲結構中,頭指針是指鏈表指向第一個結點的指針,若鏈表有頭結點,則頭指針就是指向鏈表頭結點的指針。
- 頭指針具有標識作用,故常用頭指針冠以鏈表的名字。
- 無論鏈表是否為空,頭指針均不為空。頭指針是鏈表的必要元素。
關於頭結點:
- 頭結點是為了操作的統一與方便而設立的,放在第一個元素結點之前,其數據域一般無意義(當然有些情況下也可存放鏈表的長度、用做監視哨等等)。
- 有了頭結點后,對在第一個元素結點前插入結點和刪除第一個結點,其操作與對其它結點的操作統一了。
- 首元結點也就是第一個元素的結點,它是頭結點后邊的第一個結點。
- 頭結點不是鏈表所必需的。
頭插法建立單鏈表:
尾插法建立單鏈表:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include "iostream" using namespace std; #define ListSize 10 //單鏈表的創建 typedef struct LNode { int data;//數據域 struct LNode *next;//鏈接域 }LNode,*Linklist; //單鏈表的初始化 bool InitList(Linklist &L) { L = new LNode;//創建一個新的結點作為頭結點,用頭指針L指向頭結點 L->next = NULL;//讓頭結點的指針域為空 return true; } //判斷單鏈表是否為空表:指針域那邊為空 bool ListEmpty(Linklist L) { if (L->next) return false; else return true; } //銷毀單鏈表---不保留頭結點 bool DestroyList(Linklist &L) { LNode *p; while (L) { p = L; L = L->next; delete p; } return true; } //清空單鏈表---保留頭指針和頭結點,頭結點的指針域要置為空 bool DeleteList(Linklist &L) { LNode *p, *q; p = L->next; while (p) { q = p->next; delete p; p = q; } L->next = NULL; return true; } //求單鏈表的表長 int ListLength(Linklist L) { int i = 0; LNode *p; p = L->next; while (p) { p = p->next; i++; } return i; } //取第i個元素的值 bool GetElem(Linklist L, int i, int &e) { LNode *p; p = L->next; int j = 1; while (p && j<i) { p = p->next; j++; } //查找到最后的情況以及i可能為負數的情況 if (!p || j > i) return false; e = p->data; return true; } //單鏈表的查找---查找某個元素值,返回該元素的地址 LNode *LocateElem(Linklist L, int e) { LNode *p; p = L->next; while (p && p->data != e) { p = p->next; } return p; } //單鏈表的查找---查找某個元素值,返回該元素的序號 int LocateElemInt(Linklist L, int e) { LNode *p; p = L->next; int i = 1; while (p && p->data != e) { p = p->next; i = i + 1; } if (p) return i; else return 0; } //單鏈表的插入---在第i個結點前插入值為e的結點(需要找第i-1個結點) bool ListInsert(Linklist &L, int i, int e) { LNode *p, *s; p = L; int j = 0; while (p && j < i - 1) { p = p->next; } if (!p || j > i-1) return false; s = new LNode; s->data = e; s->next = p->next; p->next = s; return true; } //單鏈表的刪除---刪除第i個結點,需要找到第i-1個結點 bool DeleteList(Linklist &L, int i, int &e) { LNode *p, *q; int j = 0; p = L; while (p && j < i - 1) { p = p->next; } if (!(p->next) || j > (i-1)) return false; q = p->next; e = q->data; p->next = p->next->next; delete q; return true; } //頭插法建立單鏈表 void CreatList_H(Linklist &L, int n) { L = new LNode; L->next = NULL; for (int i = n; i > 0; i--) { LNode *p = new LNode;//建立新結點 cin >> p->data;//讀入數據 p->next = L->next; L->next = p; } cout << "創建長度為" << n << "的單鏈表完畢!"<<endl; } //尾插法建立單鏈表 void CreatList_R(Linklist &L, int n) { L = new LNode; L->next = NULL; LNode *r = L; for (int i = 0; i < n; i++) { LNode *p = new LNode; cin >> p->data; p->next = NULL; r->next = p; r = p; } } //單鏈表內容的遍歷 void ListDisply(Linklist L) { printf("單鏈表中的內容為:"); LNode *p; p = L->next; while (p) { printf("%d ", p->data); p = p->next; } printf("\n\n\n\n"); } int main() { //創建一個鏈表 Linklist L; InitList(L); Linklist K; InitList(K); Linklist P; InitList(P); //創建三個結點 LNode *a, *b, *c; a = new LNode; b = new LNode; c = new LNode; //判斷空表 if (!ListEmpty(L)) printf("it is not empty!\n"); else printf("it is empty!\n"); //將三個結點串成串連成線兒 L->next = a; a->next = b; b->next = c; c->next = NULL; if (!ListEmpty(L)) printf("it is not empty!\n"); else printf("it is empty!\n"); //給三個結點的數據域賦值 a->data = 23; b->data = 87; c->data = 99; printf("the length of list is: %d\n", ListLength(L)); //獲取第i個元素的值 int e; GetElem(L, 2, e); printf("the value of second is:%d\n", e); //單鏈表的查找---返回地址 printf("\n\nLocateElem--23: %x\n", (unsigned)LocateElem(L, 23)); printf("LocateElem--87: %x\n", (unsigned)LocateElem(L, 87)); printf("LocateElem--99: %x\n", (unsigned)LocateElem(L, 99)); //單鏈表的查找---返回序號 printf("LocateElemInt--87: %d\n\n\n", LocateElemInt(L, 23)); //頭插法建立單鏈表---輸入幾個元素 cout << "頭插法建立單鏈表,請輸入數據:" << endl; CreatList_H(K, 5); printf("the length of list is: %d\n", ListLength(K)); //單鏈表的遍歷 ListDisply(K); //尾插法建立單鏈表---輸入幾個元素 cout << "尾插法建立單鏈表,請輸入數據:" << endl; CreatList_R(P,5); printf("the length of list is: %d\n\n", ListLength(P)); //單鏈表的遍歷 ListDisply(P); getchar(); getchar(); getchar(); return 0; }