1. 程式人生 > >朱有鵬C語言高階---4.9.4--單鏈表--頭結點(4)

朱有鵬C語言高階---4.9.4--單鏈表--頭結點(4)

朱有鵬C語言高階---4.9.4--單鏈表--頭結點(4)

 

連結串列還有另一種用法,就是把頭指標指向的第一個節點作為頭節點使用。頭結點的特點是:第一,它緊跟在頭指標後面。第二,頭結點的資料部分是空的(有時候不是空的,而是儲存整個連結串列的節點數),指標部分指向下一個節點,也就是第一個節點。

這樣看來,頭節點確實和其他節點不同。我們在建立一個連結串列時新增節點的方法也不同。頭結點在建立頭指標時一併建立並且和頭指標關聯起來;後面的真正的儲存資料的節點用節點新增的函式來完成,譬如insert_tail()。

*****連結串列有沒有頭結點是不同的。體現在連結串列的插入節點、刪除節點、遍歷節點、解析連結串列的各個演算法函式都不同。所以如果一個連結串列設計的時候就有頭結點那麼後面的所有演算法都應該這樣來處理;如果設計時就沒有頭節點,那麼後面的所有的演算法都應該按照沒有頭結點來做。實際程式設計中兩種連結串列都有人用,所以大家在看別人寫的程式碼時,一定要注意看它有沒有頭結點。

 

加入頭結點後的程式碼如下:

#include <stdio.h>
#include <strings.h>
#include <stdlib.h>

//構建一個連結串列節點
struct node
{
	int data;		//有效資料
	struct node *pNext;	//指向下一個節點的指標
};

//作用:建立一個連結串列的節點
//返回:指標,指標指向我們本函式新建立的一個節點的首地址
struct node * create_node(int data)
{
	struct node *p = (struct node *)malloc(sizeof(struct node));
	if (NULL == p)
	{
		printf("malloc error.\n");
		return NULL;
	}
	//清理申請到的堆記憶體
	bzero(p, sizeof(struct node));
	//填充節點
	p->data = data;
	p->pNext = NULL;//將來要指向下一個節點的首地址
			//實際操作時將下一個節點malloc返回的指標複製給這個
	return p;
}

//思路:由頭指標向後遍歷,直到走到原來的最後一個節點。原來最後一個節點裡面的pNext是NULL,
//現在我們將它改成new就可以了。添加了之後新節點就變成了最後一個。
//pH:頭指標,有連結串列的頭指標才能找到連結串列。new是一個新的節點
//計算添加了新的節點後共有多少個節點,然後把這個數寫進頭結點中
void insert_tail(struct node *pH, struct node *new)
{
	int cnt = 0;
	//分兩布來完成插入
	//第一步,先找到連結串列中最後一個節點
	struct node *p = pH;
	while (NULL != p->pNext)
	{
		p = p->pNext;//往後走一個節點
		cnt++;
	}
	
	//第二部,將新節點插入到最後一個節點尾部		
	p->pNext = new;
	pH->data = cnt + 1;
}

int main(void)
{
	//不能指向NULL,因為尾插法時首先會判斷頭指標的值p->pNext
	//struct node *pHeader = NULL;	
	//定義頭指標,頭結點,頭結點的資料域後面會存放多少個節點
	struct node *pHeader = create_node(0);//資料定義0表示沒放資料	

	insert_tail(pHeader, create_node(1));
	insert_tail(pHeader, create_node(2));
	insert_tail(pHeader, create_node(3));
/*
	pHeader = create_node(1);	
	//將本節點和它前面的頭指標關聯起來

	pHeader->pNext = create_node(2);
	//將本節點和它前面的頭指標關聯起來

	pHeader->pNext->pNext = create_node(3);
	//將來要指向下一個節點的首地址

	//至此建立了一個有1個頭指標+3個完整節點的連結串列	
*/
	
	//下面是4.9.3節的程式碼
	//訪問連結串列的各個節點的有效資料,這個訪問必須注意不能使用p,p1,p2,而只能使用pHeader
	
	//訪問連結串列頭結點的有效資料
	printf("header node data: %d.\n", pHeader->data);//pHeader->data等同於p->data	

	//訪問連結串列第1個節點的有效資料
	printf("node1 data: %d.\n", pHeader->pNext->data);

	//訪問連結串列第2個節點的有效資料
	printf("node2 data: %d.\n", pHeader->pNext->pNext->data);

	//訪問連結串列第3個節點的有效資料
	printf("node3 data: %d.\n", pHeader->pNext->pNext->pNext->data);
	
	return 0;
}