創建單鏈表的頭插法與尾插法詳解

創建單鏈表

關於數據結構的入門,就是從順序表和單鏈表開始。
我們不講順序表,直接從單鏈表開始我們的數據結構和算法的學習之路。

單鏈表就是一種特殊的結構體組合而成的數據結構,關於單鏈表的創建方法有很多種,但都大同小異。

在這裏插入圖片描述

正如這幅圖中所表示的那樣,單鏈表就是由可能不連續的數據所組合而成的數據結構。 其中每個數據分爲兩部分,一部分是數據存儲的位置,稱爲數據域,另外指針所存儲的地方,稱爲指針域

typedef struct Node {
	int data;                    // 存儲鏈表數據
	struct Node *next;     		//  存儲結點的地址
}LNode,*Linklist;

在進入創建鏈表之前,我們先寫好主函數的用來輸出的輸出函數。

void Illustrate(Linklist head) {
	Linklist tem = head;                 //  將頭指針的地址賦給臨時的指針
	while (tem->next != NULL) {       //  指向最後一個結點的指針域時會停止
		tem = tem->next;               //  結點不斷向後移動
		printf("%d\n", tem->data);
	}
}
int main() {
	Linklist head = NULL;            //  鏈表的頭指針
	head = Creat_list(head);        //  創建鏈表
	Illustrate(head);               //  輸出每個結點的數據域
	system("pause");
	return 0;
}

頭插法創建單鏈表

在這裏插入圖片描述

頭插法代碼:

Linklist Creat_list(Linklist head) {
	head = (Linklist)malloc(sizeof(Lnode));      //  爲頭指針開闢內存空間
	Lnode *node = NULL;                    //  定義新結點
	int count = 0;                          //  創建結點的個數
	head->next = NULL;              
	node = head->next;              	//  將最後一個結點的指針域永遠保持爲NULL
	printf("Input the node number: ");
	scanf("%d", &count);
	for (int i = 0; i < count; i++) {
		node = (Linklist)malloc(sizeof(Lnode));     //  爲新結點開闢內存空間
		node->data = i;               //  爲新結點的數據域賦值
		node->next = head->next;          //  將頭指針所指向的下一個結點的地址,賦給新創建結點的next 
		head->next = node;          //  將新創建的結點的地址賦給頭指針的下一個結點
	}
	return head;
}

頭插法創建鏈表的根本在於深刻理解最後兩條語句

	node->next = head->next;          //  將頭指針所指向的下一個結點的地址,賦給新創建結點的next 
	head->next = node;          //  將新創建的結點的地址賦給頭指針的下一個結點

創建第一個結點

執行第一次循環時,第一次從堆中開闢一塊內存空間給node,此時需要做的是將第一個結點與 head 連接起來。而我們前面已經說過,單鏈表的最後一個結點指向的是 NULL

因此插入第一個結點時,我們需要將頭指針指向的 next 賦給新創建的結點的 next , 這樣第一個插入的結點的 next 指向的就是 NULL。 接着,我們將數據域,也就是 node 的地址賦給 head->next, 這時 head->next 指向的就是新創建的 node的地址。而 node 指向的就是 NULL

接着我們創建第二個結點

因爲使用的頭插法,因此新開闢的內存空間需要插入 頭指針所指向的下一個地址,也就是新開闢的 node 需要插入 上一個 nodehead 之間。 第一個結點創建之後,head->next 的地址是 第一個 node 的地址。 而我們申請到新的一塊存儲區域後,需要將 node->next 指向 上一個結點的首地址, 而新node 的地址則賦給 head->next。 因此也就是 node->next = head->next
這樣便將第一個結點的地址賦給了新創建地址的 next 所指向的地址。後兩個結點就連接起來。

接下來再將頭結點的 next 所指向的地址賦爲 新創建 node 的地址。 head->next = node ,這樣就將頭結點與新創建的結點連接了起來。 此時最後一個結點,也就是第一次創建的結點的數據域爲0,指針域爲 NULL

創建更多的結點也就不難理解。
執行一次:
在這裏插入圖片描述

會發現,頭插法創建鏈表時候,就相當於後來居上。 後面的結點不斷往前插,而最後創建的結點在第一個結點處, 第一個創建的結點變成了尾結點。

尾插法創建單鏈表

在這裏插入圖片描述

尾插法代碼:

Linklist Creat_list(Linklist head) {
	head = (Linklist)malloc(sizeof(Lnode));          //  爲頭指針開闢內存空間
	Linklist node = NULL;           //  定義結點
	Linklist end = NULL;            //  定義尾結點
	head->next = NULL;              //  初始化頭結點指向的下一個地址爲 NULL
	end = head;                     //  未創建其餘結點之前,只有一個頭結點
	int count = 0 ;                 //  結點個數
	printf("Input node number: ");
	scanf("%d", &count);
	for (int i = 0; i < count; i++) {
		node = (Linklist)malloc(sizeof(Lnode));          //  爲新結點開闢新內存
		node->data = i;                                  //  新結點的數據域賦值
		end->next = node;                      		
		end = node;
	}
	end->next = NULL;
}

尾插法深刻理解:

end->next = node;                      		
end = node;

尾插法創建第一個結點

剛開始爲頭結點開闢內存空間,因爲此時除過頭結點沒有新的結點的建立,接着將頭結點的指針域 head->next 的地址賦爲 NULL。因此此時,整個鏈表只有一個頭結點有效,因此 head此時既是頭結點,又是尾結點。因此將頭結點的地址賦給尾結點 end 因此:end = head。 此時end 就是 head, head 就是 endend->next 也自然指向的是 NULL

尾插法創建第二個結點

創建完第一個結點之後,我們入手創建第二個結點。 第一個結點,endhead 共用一塊內存空間。現在從堆中心開闢出一塊內存給 node,將 node 的數據域賦值後,此時 end 中存儲的地址是 head 的地址。此時,end->next 代表的是頭結點的指針域,因此 end->next = node 代表的就是將上一個,也就是新開闢的 node 的地址賦給 head 的下一個結點地址。

此時,end->next 的地址是新創建的 node 的地址,而此時 end 的地址還是 head 的地址。 因此 end = node ,這條作用就是將新建的結點 node 的地址賦給尾結點 end。 此時 end 的地址不再是頭結點,而是新建的結點 node

一句話,相當於不斷開創新的結點,然後不斷將新的結點的地址當做尾結點。尾結點不斷後移,而新創的結點時按照創建的先後順序而連接的。先來新到。

尾插法創建單鏈表,結點創建完畢

最後,當結點創建完畢,最後不會有新的結點來替換 end ,因此最後需要加上一條 end->next = NULL。將尾指針的指向爲 NULL

創建更多結點也自然容易理解了一些。

執行一次:
在這裏插入圖片描述

總結

由上面的例子以及比較,我們可以看見:

  1. 頭插法相對簡便,但插入的數據與插入的順序相反;
  2. 尾插法操作相對複雜,但插入的數據與插入順序相同。

兩種創建的方法各有千秋,根據實際情況選擇不同的方法。

關於鏈表的相關其他操作,請瀏覽相關文檔。

                                </div><div><div></div></div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-60ecaf1f42.css" rel="stylesheet">
                            </div>
</article>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章