資料結構之線性表的實現

2022-03-26 14:19:23 字數 4350 閱讀 3844

在生活中其實處處可見線性表的例子。比如乙個班級的小朋友,乙個跟著乙個排著隊,有乙個打頭,有乙個收尾,當中的小朋友 每乙個都知道他前面乙個是誰,他後面乙個是誰,這樣如同有一根線把他們串聯起來 了。 就可以稱之為線性表。

所以線性表的定義為:零個或多個資料元素的有限序列。

首先它是乙個序列。 也就是說,元素之間是有順序的,若元素存在多個,則第一 個元素無前驅,最後乙個元素無後繼,其他每個元素都有且只有乙個前驅和後繼。 然後,線性表強調是有限的,小朋友班級人數是有限的,元素個數當然也是有限的。

那麼定義好的線性表應該具有哪些操作呢?還是以前面排好隊的小朋友舉例子,我們可以知道這個隊伍的長度,也可以找出隊伍裡的某個小朋友,有時我們還需要知道隊伍裡有沒有乙個叫小明的同學,這種查詢某個元素是否存在也是線性表的必要操作。對於乙個幼兒園來說,加入乙個新的小朋友到佇列中,或因某個小朋友生病,需要移除某個位置,也是很正常的情況,因此對於乙個線性表來說,插入資料和刪除資料都是必須的操作。所以我們可以定義這樣乙個線性表的抽象資料型別。

型別名稱:線性表(list)  

資料物件集:線性表是 n (≥

0)個元素構成的有序序列( a1, a2, ...,an )

操作集:線性表l list,整數i表示位置,元素x  elementtype,

線性表基本操作主要有:

1、list makeempty():初始化乙個空線性表l;

2、elementtype getelem( int

k, list l ):根據位序k,返回相應元素 ;

3、int

4、void insert( elementtype x, int

i, list l):在位序i前插入乙個新元素x;

5、void delete( int

i, list l ):刪除指定位序i的元素;

6、int length( list l ):返回線性表l的長度n

線性表這種有限序列的邏輯結構我們怎樣在計算機中以物理形式儲存起來呢?我們有兩種實現方式:順序儲存和鏈式儲存。

線性表的順序儲存結構,指的是用一段位址連續的儲存單元依次儲存線性表的資料元素。

#include//

巨集定義

#define maxsize 50 //

儲存空間初始量分配

#define ok 1

#define error 0

#define true 1

#define false 0

typedef

intstatus;

typedef

int elemtype;//

定義int型別的別名為elemtype

//初始化乙個線性表結構體

typedef struct

sqlist;

//獲取線性表l中的第i個元素,並傳給變數e,

status getelem(sqlist l,int i,*e)

*e = l.data[i-1

];

return

ok;}

//在l中的第i個位置插入乙個元素e

status insertlist(sqlist *l,int

i,elemtype e)

if(i<1 || i>l->length)

for(k=l->length-1;k>=i-1;k--)

l->length[i-1]=e;//

將新元素插入

l->length++;//

線性表長度加1

return

ok;}

//刪除l中的第i個元素,並用變數e返回其值

status listdlelte(sqlist *l,int i,elemtype *e)

if(i<1 || i>l->length)

*e = l->data[i-1

];

for(k=i;k>l->length;k++)

l->length--;

return

ok;}

線性表的順序儲存結構,在讀資料時,不管是哪個位置,時間複雜度都是 0(1); 而插入或刪除時,時間複雜度都是 o(n)。這就說明 ,它比較適合元 素個數不大變化,而更多是訪問資料的應用。順序儲存的優缺點有。

優點 缺點

無須為表示表中元素之 間的邏輯關係而增加額 外的儲存空間 

插入和刪除需要移動大量元素

可以快速的訪問表中任意位置的元素

當線性表長度變化較大時,難以確定儲存空間的容量,造成儲存空間的碎片

既然順序儲存因為其插入和刪除元素需要移動大量的元素而造成時間效能上的浪費。那麼有沒有一種儲存結構能彌補順序儲存結構的缺點呢。當然是有的,就是我們接下來要講的鏈式儲存結構。

和順序儲存不同的是,鏈式儲存不需要向順序儲存那樣開闢一塊連續的儲存空間來儲存線性表元素,而是分散的插入到空閒的記憶體空間中。這樣的話,前面的元素如果找到後面的元素就需要知道後乙個元素的位址。因此鏈式儲存的線性表結點就由兩部分資訊組成(儲存資料元素資訊的資料域和儲存後繼結點位址的指標域)。鍊錶中的每個結點都存有乙個指標域,因此也稱作單鏈表。

#includetypedef 

intelemtype

typedef

intstatus

#define ok 1

#define error 0

#define true 1

#define false 0

/*單鏈表結點儲存結構

*/typedef

struct

nodenode;

單鏈表的結點定義好了,那麼我們如何來遍歷單鏈表的每乙個結點元素呢?

既然元素結點的指標域儲存了後繼元素的位址,這樣的話我們就可以定義乙個指標變數來遍歷所有的結點元素。

typedef struct node *linklist;    //

定義指向單鏈表結點結構的指標變數,別名為linklist

我們 假設p 是指向錢性表第 i 個元素的指標,則該結點 aj 的資料域 我們可以用 p->由回 來表示, p->由恒的值是乙個資料元素,結點 aj 的指標域可以用 p->next 來表示, p->next 的值是乙個指標。 p->next 指向誰呢? 當然是指向第 i+l 個 元素,即指向 ai+1 的指標。

所以線性表的鍊錶操作定義為

//

獲取單鏈表中的第i個元素

status getelem(linklist l,int i,elemtype *e)

if(!p || j>i)

*e = p->data;

return

ok;}

//在l中第i個位置之前插入新的資料元素e,l的長度增加1

status listinsert(linklist *l,int

i,elemtype e)

if(!p || j>i)

s = (linklist)malloc(sizeof(node));//

建立乙個存放指標變數的新結點

s->data =e;

s->next = p->next;

p->next =s;

*l->length++;

return

ok;}

//刪除l中的第i個資料元素,並用e返回其值, l的長度減1

status listdelete(linklist *l,int i,elemtype *e)

if(!(p->next) || j>i)

q = p->next;

p->next = q->next;

*e = q->data;

*l->length--;

free

(q);

return

ok;}

線性表的鏈式儲存結構,在讀資料時,由於後繼元素只能通過前驅元素的指標來訪問,所以時間複雜度是 o(n); 而插入或刪除時,要先遍歷再插入或刪除,遍歷的複雜度為o(n),插入或刪除的時間複雜度是 o(1)。這就說明 ,它比較適合元需要頻繁插入或刪除元素的應用。

順序儲存

鏈式儲存

查詢(時間效能)

o(1)

o(n)

插入和刪除(時間效能)

順序儲存結構需要移動表長一半的元素, 時間為o(n) 

單鏈表在找出某位置的指標後,插入和刪除間僅為o(1)

空間效能

服序儲存結構需要預先分配記憶體,分大了浪費, 分小了易發生上溢 

單鏈表不需要預先分配儲存空間,只要有就可以分配, 元素個數也不受限制

mysql 線性表 資料結構之線性表

概要 參考 大話資料結構 把常用的基本資料結構梳理一下。線性表定義 線性表 list 零個或多個資料元素的有限序列。若將線性表記為 a 1,cdots,a a i,a cdots,a n 則表中 a 領先於 a i a i 領先於 a 稱 a 是 a i 的直接前驅元素,a 是 a i 的直接後繼元...

資料結構之線性表

從現在開始,我們開始討論如何實現一些常用的資料結構和其中的一些經典演算法.等把資料結構講完了.我可能會繼續討論vc 的程式設計只是以及vs平台下的c c 開發等等.呵呵.我們進入正題吧.我在這裡就只實現線性表的連表結構.當然了,這裡實際上包含了好多知識.我希望大家在引用的時候.一定要領悟裡面的一些變...

資料結構之線性表

線性表是具有相同特性的資料元素的乙個有限序列。該序列中所含元素的個數叫做線性表的長度,用n表示,n 0。當n 0時,表示線性表是乙個空表,即表中不包含任何元素。設序列中第i i表示位序 個元素為ai 1 i n 線性表的一般表示為 a1,a2,ai,ai 1,an include include d...