頭結點,頭指針,首元節點分類

最近在學習鏈表,出現了幾個容易混淆的概念,分別是頭結點,頭指針,首元結點,他們三個到底是什麼關係呢?
頭結點:
       頭結點是鏈表裏面第一個結點,他的數據域可以不存放任何信息(有時候也會存放鏈表的長度等等信息),他的指針區域存放的是鏈表中第一個數據元素的結點(就是傳說中的首元結點)存放的地址。
     
       1、防止單鏈表是空的而設的.當鏈表爲空的時候,帶頭結點的頭指針就指向頭結點.如果當鏈表爲空的時候,單鏈表沒有帶頭結點,那麼它的頭指針就爲NULL.

2、是爲了方便單鏈表的特殊操作,插入在表頭或者刪除第一個結點.這樣就保持了單鏈表操作的統一性!

3、單鏈表加上頭結點之後,無論單鏈表是否爲空,頭指針始終指向頭結點,因此空表和非空表的處理也統一了,方便了單鏈表的操作,也減少了程序的複雜性和出現bug的機會。

4、對單鏈表的多數操作應明確對哪個結點以及該結點的前驅。不帶頭結點的鏈表對首元結點、中間結點分別處理等;而帶頭結點的鏈表因爲有頭結點,首元結點、中間結點的操作相同 ,從而減少分支,使算法變得簡單 ,流程清晰。對單鏈表進行插入、刪除操作時,如果在首元結點之前插入或刪除的是首元結點,不帶頭結點的單鏈表需改變頭指針的值,在TurboC 算法的函數形參表中頭指針一般使用指針的指針(在C+ +中使用引用 &);而帶頭結點的單鏈表不需改變頭指針的值,函數參數表中頭結點使用指針變量即可,對初學者更易接受。
首元結點:
       首元結點就是鏈表裏面第一個元素的結點,也就是a1的結點。在存在頭結點的情況下,頭結點的指針區域指的就是首元結點。
頭指針:
       如果鏈表裏有頭結點,頭指針就指向頭結點;如果沒有頭結點,頭指針就指向首元結點。


這三個概念對單鏈表,雙向鏈表,循環鏈表均適用。

②如果用C語言描述單鏈表如下:
typedef struct node{
          DataType data;//節點的數據域
          struct node *next;//節點的指針域
}ListNode;
typedef ListNode *LinkList;
ListNode *p;//p是節點
LinkList head;//head是頭指針
注意最後一句:"LinkList head",這是定義了一個頭結點,前面已經用typedef定義了LinkList,既“typedef ListNode *LinkList;”這句,這就說明LinkList head 定義後 head實際上是一個LinkNode類型的指針,這是我們單單看最後兩句的定義而忽略其字面意思而言的話,p和head實際上是同一種類型的變量,都是ListNode類型的指針,只不過最後一句LinkList類型是用typedef定義的,所以沒有“*”號。
    因爲刪除或者插入操作有時會修改實參的指針(比如頭結點爲空的時候插入節點,這是就修改了頭結點),那麼就必須將相應的形參說明爲指針的指針,函數電泳時將實參指針的地址傳遞給相應的形參。例如:剛剛初始化的時候頭結點head爲空,如果這時插入節點p(由上可知p是ListNode*類型的,是個指針,把它當做地址)時應該是head=p;這就改變了head的地址,所以在傳參數的時候,函數的形參一般都是"Insert(LinkList *head,DataType x)",
 
    方便在第1個位置進行插入、刪除操作時同其他位置一樣。加了頭結點之後,插入、刪除都是在後繼指針next上進行操作,不用動頭指針;若不加頭指針的話,在第1個位置插入或者刪除第1個元素時,需要動的是頭指針。例如:在進行刪除操作時,L爲頭指針,p指針指向被刪結點,q指針指向被刪結點的前驅,對於非空的單鏈表:
1.帶頭結點時
刪除第1個結點(q指向的是頭結點):q->next=p->next; free(p);
刪除第i個結點(i不等於1):q->next=p->next;free(p);
2.不帶頭結點時
刪除第1個結點時(q爲空):L=p->next; free(p);
刪除第i個結點(i不等於1):q->next=p->next;free(p);
結論:帶頭結點時,不論刪除哪個位置上的結點,用到的代碼都一樣;不帶頭結點時,刪除第1個元素和刪除其它位置上的元素用到的代碼不同,相對比較麻煩。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章