數據結構(第二課)--線性表

數據結構,之前感覺不到其重要性,線性表對我們以後的編程會有什麼幫助呢,今天看到關於一個java方面的問題才發現其重要性,在java中,我們所用到的集合list等,都是通過線性表來實現的,瞭解了線性表,我們對這些的理解會更深入,用起來會更加的得心應手,程序中的數據大致分爲四種姐幫你的邏輯結構,集合,線性結構,樹形結構,圖狀結構或網狀結構,對於數據的不同邏輯結構,計算機在物理磁盤上通常有點2中方式,一個是鏈式存儲結構,一種是順序存儲結構。

線性表是線性結構中最常用的數據結構。

順序存儲結構:

線性表的順序存儲結構是用一組地址連續的存儲單元一次存放線性表的元素,因此線性表中的數據元素邏輯上和物理存儲的關係是一致的,程序獲取該數據的地址的時間和獲取該數據所用的時間是相同的,因爲每個元素的存儲都是緊挨着的,而每一個元素的長度也是相同的,所以我們可以根據其地址很容易的找到這個元素,所以說是做到了隨機的存取,這也是順序存儲的一個優點。順序結構的存儲底層是通過數組來實現的,我們在存儲的時候就和我們在數組中存放數值是一樣的,所以說當對其進行插入,刪除操作的時候,我們可能要移動一般的數據,這樣的效率是比較低的。

鏈式存儲結構:

鏈式存儲結構是採用一組地址任意的存儲單元來存放 線性表中的元素,鏈式結構的線性表會按照線性的邏輯順序來保存數組元素而在每一個數據元素中保存一個下一個元素的引用,由於不是按照順序結構來寫的,所以在我們用其執行查找操作的時候,是比較麻煩的,因爲要遍歷每一個元素,通過每一個元素的引用去尋找下一個,然後依次進行。但是由於每一個元素都要保存下一個元素的地址,這也無疑增大了內存的開銷,但是對其執行刪除,插入的操作的時候是比較方便的,我們只需要去找到這個位置,通過改變其引用的指向就可以了而不需要移動每一個元素。

線性表的鏈式表示和實現

//  初始化一個線性表
Status InitList Sq (SqList &L){
	L.elem = (ElemType * )malloc (LIST INIT SIZE * sizeof (ElemType));
	if (!L.elem)
		exit (OVERFLOW);
	L.length = 0;
	L.listsize = LIST INIT SIZE;
	return OK;
}
//順序結構的線性表中添加一個元素的方法
Status ListInsert _Sq(SqList &L, int i, ElemType e){
	if (i < 1 || i > L.length + 1)
		return false;
	if (L.length > L.listsize){
		newbase = (ElemType *) relloc (L.elem (L.listsize+ LISTINCREATMENT)*sizeof(ElemType));
		L.elem = newbase;
		L.listsize + = LISTINCREATEMENT;
		if (! newbase)
			exit (StakOverFlow);
	}
	q = & (L.elem[i-1];
	for (p = &(L.elem[L.length-1]; p >= q; p--)
		*p = *(p+1);
	*q = e;
	++ L.length;
}
//順序結構的刪除方式
Status ListDelete (Sqlist &L, int i,ElemType &e){
	if (i < 1 || i > L.length + 1)
		return false;
	p  =  &(L.elem[i-1]);
	e = *p;
	q = L.length;
	for (++p; p < =q; p++){
		*(p-1) = *p;
	}
	--L.length;
	return OK;
}

順序表中的兩個表的合併

//將兩個線性表的元素進行合併
void union (List &a, List b){
	a.len = ListLength (a);
	b.len = ListLength (b);
	for(i = 1; i < b.len; i++){
		GetElem(b, i, e);
		if(!LocateElem(a, e, equal))
			ListInsert(a, a.len++, e);
	}
}
//將之前排好順序的線性表中再插入數據,此處假設數據按升序排列
void mergList (List a, List b, List &c){
	a.len = ListLength (a);
	b.len = ListLength (b);
	i = j = 1;
	k = 0;
	while (i <= a.len && j <= b.len){
		GetElem (a, i, ai);
		GetElem (b, j, bj);
		if(ai < bj){
			ListInsert (c, k++; ai);
			i++;
		}
		else {
			ListInsert (c, k++; bj);
			j++;
	}
	while (i <= a.len){
		GetElem (a, i, ai);
		ListInsert (a, i, ai);
		i++;
	}
	while (j <= b.lem){
		GetElem (b, j, bi);
		ListInsert (b, j, bj);
		j++;
	}
}

線性表的鏈式表示涉及到的一些算法


//鏈式表獲取元素
Status GetElem (LinkList L, int i, ElemType &e){
	p = L->next; j = 1;
	if (!p || i < j)
		return error;
	while (p && j < i){
		p = p->next;
		++ j;
	}
	e = p -> data;
	return OK;
}
//單鏈表中插入數據
Status ListInsert (LinkList & L, int i, ElemType e){
	p = L->next; j = 1;
	if (!p || i < j)
		return error;
	while (p && i > j){
		p = p->next;
		++ j;
	}
	s = (LinkList) malloc (sizeof(LNode));
	s -> data = p -> data;
	s -> next = p ->next;
	p ->next = s;
	return OK; 
}
//單鏈表中刪除數據
Status ListDelete (LinkList & L, int i, ElemType & e){
	p = L->next; j = 1;
	if(!p || i < j)
		return error;
	while (p && i > j){
		p = p ->next;
		++ j;
	}
	q = p->next;
	p  = q->next;

}	
線性表的鏈式表示又有這麼幾種,一個是循環鏈表,一個是雙向鏈表,循環鏈表就是最後一個節點的後繼指向的是第一個結點,這樣當查找一個結點的時候可以從任何一個結點開始都是可以的,雙向鏈表就是每一個節點存在一個前驅,也就是每個節點有兩個指針域,一個指向前面,也就是它的前驅,另一個指向的是它的後繼。雙向鏈表在插入節點和刪除節點的時候是比較麻煩的。

線性表的應用:

一元多項式的相加

解決一元多項式相加的問題,我們可以通過線性表來模擬實現,順序表模擬,每一個表的位置代表指數,表中的數值代表的是係數,鏈表模擬的話,爲每一個結點增加一個數據域,一個數據域用來保存係數,一個用來保存指數,這樣,通過順序表保存的話會造成空間上的浪費,通過鏈式表來實現可以最大限度的充分利用空間。

利用鏈式表來實現相加的話,也就是兩個表的合併,將第一個鏈表的元素和第二個元素進行比較,如果第二鏈表中的結點有和這個結點的指數相同的,就將這兩個結點的係數相加,然後將其和作爲第二個鏈表中係數存放,如果沒有和這個結點相同的,就將該結點家在第二個鏈表的後面。通過這來完成多項式的相加。

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