數據結構與算法學習筆記02_2(線性表)

數據結構與算法學習筆記02_2(線性表)

 

2、線性表的鏈式存儲結構

 

單鏈表

除了存儲其本身的信息外,還需存儲一個指示其直接後繼的存儲位置的信息。

我們把存儲數據元素信息的域稱爲數據域,把存儲直接後繼位置的域稱爲指針域。鏈表中的第一個結點的存儲位置叫做頭指針,最後一個結點指針爲(NULL)

 

頭指針與頭結點的異同

1、頭指針是指鏈表指向第一個結點的指針,若鏈表有頭結點,則是指向頭結點的指針。

2、頭指針是鏈表的必要元素

3、頭結點是爲了操作的統一和方便而設立的,放在第一個元素的結點之前,其數據域一般無意義(但也可以用來存放鏈表的長度)。

4、頭結點不一定是鏈表的必須要素

 


實現:

typedefstructNode

{

       ElemType  data;     // 數據域

       struct  Node*Next// 指針域

} Node;

typedef  struct Node*LinkList;

 

單鏈表的讀取:

獲得鏈表第i個數據的算法思路:

聲明一個結點p指向鏈表第一個結點,初始化j從1開始;

當j<i時,就遍歷鏈表,讓p的指針向後移動,不斷指向一下結點,j+1;

若到鏈表末尾p爲空,則說明第i個元素不存在;

否則查找成功,返回結點p的數據。

實現:

status GetElem(LinkList L, int i, ElemType* e){
	int j;
	LinkList p;
	p = L->next;
	j = 1;
	
	while (p&&j<i)
	{
		p = p->next;
		++j;
	}
	if (!p||j>i)
	{
		return ERROR;
	}
	*e = p->data;
	return Ok;
}

由於單鏈表的結構中沒有定義表長,所以不能實現知道要循環多少次,因此也就不方便使用for來控制循環。

 

單鏈表的插入


我們思考後發覺根本用不着驚動其他結點,只需要讓s->next和p->next的指針做一點改變。

s->next= p->next;

p->next= s;

這兩句是無論如何不能弄反的。

 

單鏈表第i個數據插入結點的算法思路:

聲明一結點p指向鏈表頭結點,初始化j從1開始;

當j<1時,就遍歷鏈表,讓p的指針向後移動,不斷指向下一結點,j累加1;

若到鏈表末尾p爲空,則說明第i個元素不存在;

否則查找成功,在系統中生成一個空結點s;

將數據元素e賦值給s->data;

單鏈表的插入剛纔兩個標準語句;

返回成功。

實現:

Status ListInsert(LinkList* L, int i, ElemType e){
	int j;	
	LinkList p, s;

	p = *L;
	j = 1;

	while (p&&j<i)
	{
		p = p->next;
		j++
	}
	if (!p||j>i)
	{
		return ERROR;
	}
	s = (Listlist)malloc(sizeof(Node));
	s->data = e;

	s->next = p->next;
	p->next = s;
	return Ok;
}

單鏈表的刪除


單鏈表第i個數據刪除結點的算法思路:

聲明結點p指向鏈表第一個結點,初始化j=1;

當j<1時,就遍歷鏈表,讓P的指針向後移動,不斷指向下一個結點,j累加1;

若到鏈表末尾p爲空,則說明第i個元素不存在;

否則查找成功,將欲刪除結點p->next賦值給q;

單鏈表的刪除標準語句p->next = q->next;

將q結點中的數據賦值給e,作爲返回;

釋放q結點。

實現:

Status ListDelete(LinkList *L, int i, ElemType *e){
	int j;
	LinkList p, q;

	p = *L;
	j = 1;
	
	while (p->next&&j<i)
	{
		p = p->next;
		++j;
	}
	if (!(p->next)||j>i)
	{
		return ERROR;
	}
	q = p->next;
	p->next = q->next;

	*e = q->data;
	free(q);

	return Ok;
}

效率分析:

無論是單鏈表插入還是刪除算法,它們其實都是由兩個部分組成:第一部分就是遍歷查找第i個元素,第二部分就是實現插入和刪除元素。從整個算法來說,我們很容易可以推出它們的時間複雜度都是O(n)。

 

再詳細點分析:

如果在我們不知道第i個元素的指針位置,單鏈表數據結構在插入和刪除操作上,與線性表的順序存儲結構是沒有太大優勢的。

但如果,我們希望從第i個位置開始,插入連續10個元素,對於順序存儲結構意味着,每一次插入都需要移動n-i個位置,所以每次都是O(n)。

 

而單鏈表,我們只需要在第一次時,找到第i個位置的指針,此時爲O(n),接下來只是簡單地通過賦值移動指針而已,時間複雜度都是O(1)。

顯然,對於插入或刪除數據越頻繁的操作,單鏈表的效率優勢就越是明顯啦~

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