線性表使用順序(數組)存儲時有個弊端,那就是在插入和刪除時需要大量的移動數據,這顯示是非常消耗時間的,所以可以採用鏈式存儲,即有一個指針域(單鏈表),來記錄下個結點的存儲位置(地址),這樣在插入和刪除結點時只需要修改指針域即可,從而大量減少移動數據所消耗的時間。來看鏈表的定義:
struct node { int data; struct node *next; };
其中有兩個元素,data爲數據域,用於存儲數據,next爲指針域,用於存儲下個結點的位置(地址)。那麼什麼是頭指針呢?我們把指向第一個結點的指針稱爲頭指針,那麼每次訪問鏈表時都可以從這個頭指針依次遍歷鏈表中的每個元素,例如:
struct node first; struct node *head = &first;
這個head指針就是頭指針。
這個頭指針的意義在於,在訪問鏈表時,總要知道鏈表存儲在什麼位置(從何處開始訪問),由於鏈表的特性(next指針),知道了頭指針,那麼整個鏈表的元素都能夠被訪問,也就是說頭指針是必須存在的。示例如下:
- #include <stdio.h>
- struct node {
- int data;
- struct node *next;
- };
- int main(void)
- {
- struct node *head, first, second;
- head = &first;
- first.data = 1;
- first.next = &second;
- second.data = 2;
- second.next = NULL;
- while (head) {
- printf("%d\n", head->data);
- head = head->next;
- }
- return 0;
- }
那麼什麼又是頭結點呢?很多時候,會在鏈表的頭部附加一個結點,該結點的數據域可以不存儲任何信息,這個結點稱爲頭結點,
頭結點的指針域指向第一個結點,例如:
struct node head, first; head.next = &first;那麼這裏的頭指針又是誰呢,不在是指向第一個結點的指針,而是指向頭結點的指針,例如:
struct node *root = &head;
即root指針纔是頭指針。示例如下:
- #include <stdio.h>
- struct node {
- int data;
- struct node *next;
- };
- int main(void)
- {
- struct node *root, head, first, second;
- root = &head;
- root->data = 0;
- root->next = &first;
- first.data = 1;
- first.next = &second;
- second.data = 2;
- second.next = NULL;
- while (root) {
- printf("%d\n", root->data);
- root = root->next;
- }
- return 0;
- }
注:在Linux kernel中,定義頭結點使用宏LIST_HEAD。