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

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

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

三、單鏈表加上頭結點以後,不管單鏈表是否爲空,頭指針始終指向頭結點,所以空表和非空表的處理也統一了,方便了單鏈表的操做,也減小了程序的複雜性和出現bug的機會。

四、對單鏈表的多數操做應明確對哪一個結點以及該結點的前驅。不帶頭結點的鏈表對首元結點、中間結點分別處理等;而帶頭結點的鏈表由於有頭結點,首元結點、中間結點的操做相同 ,從而減小分支,使算法變得簡單 ,流程清晰。對單鏈表進行插入、刪除操做時,若是在首元結點以前插入或刪除的是首元結點,不帶頭結點的單鏈表需改變頭指針的值,在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個元素和刪除其它位置上的元素用到的代碼不一樣,相對比較麻煩。
相關文章
相關標籤/搜索