**
鍊錶中第乙個結點的儲存位置叫做頭指標,那麼整個鍊錶的訪問就必須是從頭指標開始進行了。之後的每乙個結點,其實就是上乙個的後繼指標指向的位置。
這裡有個地方要注意,就是對頭指標概念的理解,這個很重要。「鍊錶中第乙個結點的儲存位置叫做頭指標」,如果鍊錶有頭結點,那麼頭指標就是指向頭結點資料域的指標。畫乙個圖吧。
頭指標就是鍊錶的名字。頭指標僅僅是個指標而已。
頭指標具有標識作用,故常用頭指標冠以鍊錶的名字。
無論鍊錶是否為空,頭指標均不為空。頭指標是鍊錶的必要元素。
[cpp]view plain
copy
?
//這裡插入關於鍊錶中有無頭節點進行初始化鍊錶知識
//首先明白頭指標與頭結點的關係:
//定義結點的結構體
//typedef struct lnodelnode,*linklist;//則定義linklist l;時,l為鍊錶的頭指標。
////l=(linklist) malloc (sizeof(lnode)); //建立乙個結點,此處返回給l的是乙個指標,並且賦給了頭指標。
//l->next=null; //這裡說明我建立了乙個頭結點,即同時運用了頭指標和頭結點。
//這麼方便只要加上->next就說明建立了頭節點。不過你想想頭指標是沒有next的,只有頭結點才有,所以就不難理解了
//帶頭結點初始化
//node *head; //宣告頭結點
//首先第一眼看到(*head)->next=null;和我們剛才所說是不是一樣,只要頭指標一旦運用了next操作就自動建立了頭結點
//但是我們今天的重點不在於這個,更多在於node **head,對於兩個指標的操作理解
//第乙個指標*head,表明了head這個指標變數儲存的是另外乙個指向結構體node的指標,第二個指標,即*head作為乙個整體
//其結果是乙個指標,其指向的內容就是結構體node。經過這麼一理解,對於頭指標,頭結點,首元節點的關係就非常明朗了
// void initlist(node **head)
//帶頭結點尾方便了首元節點和其他節點一樣,統一了操作
//方式一:
// void creatlist(node **head)
// else
// }
//}//呼叫creatlist(&head);//這句話表明了形參node **head,只有第乙個*才是起作用了,第個*號是和head聯絡在一起,作為整體使用的
//方式二:
// void creatlist(node *head)
//呼叫creatlist(head);
////不帶頭結點初始化
//方式一:
//void initlist(node **head)
//呼叫initlist(&head);
////方式二:
//void initlist(node *head)
//呼叫initlist(head);
//不帶頭結點尾插入,第乙個節點與其他節點分開操作
//void creatlist(node **head)
// else
// p=t;
// }
// else
// i++;
// }
//}//呼叫creatlist(&head);
//其實從上面就可以知道,其實有頭結點對於我們來說是一種更加明智更加方便的操作
//這裡插入關於鍊錶中有無頭節點進行初始化鍊錶知識
//首先明白頭指標與頭結點的關係:
//定義結點的結構體
//typedef struct lnodelnode,*linklist;//則定義linklist l;時,l為鍊錶的頭指標。
////l=(linklist) malloc (sizeof(lnode)); //建立乙個結點,此處返回給l的是乙個指標,並且賦給了頭指標。
//l->next=null; //這裡說明我建立了乙個頭結點,即同時運用了頭指標和頭結點。
//這麼方便只要加上->next就說明建立了頭節點。不過你想想頭指標是沒有next的,只有頭結點才有,所以就不難理解了
//帶頭結點初始化
//node *head; //宣告頭結點
//首先第一眼看到(*head)->next=null;和我們剛才所說是不是一樣,只要頭指標一旦運用了next操作就自動建立了頭結點
//但是我們今天的重點不在於這個,更多在於node **head,對於兩個指標的操作理解
//第乙個指標*head,表明了head這個指標變數儲存的是另外乙個指向結構體node的指標,第二個指標,即*head作為乙個整體
//其結果是乙個指標,其指向的內容就是結構體node。經過這麼一理解,對於頭指標,頭結點,首元節點的關係就非常明朗了
// void initlist(node **head)
//帶頭結點尾方便了首元節點和其他節點一樣,統一了操作
//方式一:
// void creatlist(node **head)
// else
// }
//}//呼叫creatlist(&head);//這句話表明了形參node **head,只有第乙個*才是起作用了,第個*號是和head聯絡在一起,作為整體使用的
//方式二:
// void creatlist(node *head)
//呼叫creatlist(head);
////不帶頭結點初始化
//方式一:
//void initlist(node **head)
//呼叫initlist(&head);
////方式二:
//void initlist(node *head)
//呼叫initlist(head);
//不帶頭結點尾插入,第乙個節點與其他節點分開操作
//void creatlist(node **head)
// else
// p=t;
// }
// else
// i++;
// }
//}//呼叫creatlist(&head);
//其實從上面就可以知道,其實有頭結點對於我們來說是一種更加明智更加方便的操作
一、兩者區別:
1、不帶頭結點的單鏈表對於第乙個節點的操作與其他節點不一樣,需要特殊處理,這增加了程式的複雜性和出現bug的機會,因此,通常在單鏈表的開始結點之前附設乙個頭結點。
2、帶頭結點的單鏈表,初始時一定返回的是指向頭結點的位址,所以一定要用二維指標,否則將導致記憶體訪問失敗或異常。
這點就是指標方面的知識點了。不懂了就回去好好看一下指標
3、帶頭結點與不帶頭結點初始化、插入、刪除、輸出操作都不樣,在遍歷輸出鍊錶資料時,帶頭結點的判斷條件是while(head->next!=null),
而不帶頭結點是while(head!=null),雖然頭指標可以在初始時設定,但是如1所述,對於特殊情況如只有乙個節點會出現問題。
二、為什麼不帶頭結點初始化有2種方式,而帶頭結點只有1種方式呢?
因為不帶頭結點宣告node *head 時;c編譯器將其自動初始化為null,於是根本不需要呼叫initlist(head);也即不帶頭結點的初始化是個偽操作。而帶頭結點的初始化在堆開闢了一段記憶體,需要修改head指標變數指向的位址(即head的值),所以要修改head的值,必須傳儲存head變數的位址(即二維指標)。而直接呼叫creatlist(head);相當於傳head變數的值,函式修改的是head的副本,無法真正改變head的值。
其實這個就是上面所說的第二點內容
三、其實本質上還是傳值,傳址的問題,只不過指標本身儲存的位址,讓這個過程變得有點糾結。在函式呼叫需要修改指標變數的指向(value)時,
應該傳遞指標變數的位址(address)。
另外,對於函式的形參是指標時,只要該引數不在左邊(即都是右值操作),二維指標(形參)就可以簡化為一維指標。如上面帶頭結點的尾插
簡化版本。
單鏈表 頭指標
include include malloc的標頭檔案 define ok 0 define error 1 define malloc error 2 typedef int elementtype typedef struct node node typedef node pnode 重新命名結...
線性表頭結點 頭指標儲存
本文主要是跟同學討論到資料結構裡面線性表的頭指標裡面儲存了什麼東西。那麼在鍊錶裡面頭指標到底存了恩什麼呢?首先,對於頭結點的理解,我們需要結合頭指標來了解,所謂的頭指標就是用來指示鍊錶的第乙個結點的儲存位置,也就是說儲存的是第乙個節點物件的位置。這裡補充一下,由於最後乙個元素沒有直接後繼,所以線性表...
單鏈表 頭指標與頭結點
頭指標 頭指標是指鍊錶指向第乙個結點的指標,若煉表有頭結點,則是指向頭結點的指標。頭指標具有標識作用,所以常用頭指標冠以鍊錶的名字。無論鍊錶是否為空,頭指標均不為空。頭指標是鍊錶的必要元素。頭結點 它是為了操作的統一和方便設立的,放在第乙個元素的結點之前,其資料域一般無意義 但也可以用來存放鍊錶的長...