資料結構與演算法(3) 鍊錶

2021-04-06 16:22:22 字數 4023 閱讀 5575

資料結構與演算法(3)— 鍊錶

(mi6236)

1、鍊錶簡述

鏈結表(linkedlist)分為線性鏈結表(用於線性表)和非線性鏈結表(用於樹型結構,圖型結構等)。

乙個鍊錶由n個(n>=0,若n=0,則稱為空表)節點所組成,每個節點除了包含有儲存資料元素的值域外還包含有用來實現資料元素之間邏輯關係的乙個或若干個指標域,每個指標域的值為其後繼元素或前驅元素所在結點的存貯位置,若某個指標域不需要指向任何結點,則令它的值為null。

在乙個鏈結表中,若每個結點只包含有乙個指標域,則被稱為單鏈表,否則被稱為多鍊錶。對於結尾資料結構來說,由於資料元素之間是1:1的聯絡,所以當進行鏈結存貯時,一種方式是:在每個結點中只設定乙個指標域,用以指向其後繼結點,這樣構成的鏈結表稱為單向鏈結表;另一種方法是:在每個結點中設定兩個指標域,分別用以指向其前驅結點和後繼結點,這樣構成的鏈結表稱為雙向鏈結表。

每個鍊錶都有乙個指標指向其第乙個結點,稱做表頭指標。沿著表頭指標可以訪問到任乙個結點。線性單鏈表分為帶頭結點和不帶頭結點兩種型別,它們之間區別主要體現在其結構上和演算法操作上。在結構上,帶頭結點的單鏈表不管鍊錶是否為空,均含有乙個頭結點;而不帶頭結點的單鏈表為空。在操作上帶頭結點的單鏈表的初始化為申請乙個頭結點,且在任何結點位置進行操作演算法一致;而不帶頭結點的單鏈表讓頭指標為空,同時其他操作要特別注意空表和第乙個結點的處理。常常為了運算的方便在第乙個結點之間增設乙個結點,把它稱為附加表頭結點,並讓鏈結表的表頭指標指向這個結點,而這個結點的指標域指向第乙個結點。

順序表和煉表各有優缺點,在實際應用中,應根據問題的特點具體分析:

基於空間考慮,當要求儲存的線性表公升序變化不大,易於事先確定其大小時,為了節約儲存空間,宜採用順序表;反之,當線性表公升序變化大,難以估計其儲存規模時,採用動態鍊錶。

基於時間考慮,若線性表的操作主要是進行查詢,很少做插入和刪除操作時,採用順序表做儲存結構為宜;反之,若需要對線性表進行頻繁插入或刪除等操作時,宜採用鍊錶做儲存結構。且,若鍊錶的插入和刪除主要發生在表的首尾兩端,則採用指標表示的單迴圈鍊錶。

2、單鏈表儲存結構c語言描述。

#include

#include

#define limit 10

typedef int elemtype;

typedef struct nodelnode,*linklist;

3、單鏈表基本函式演算法描述

注:一下程式在vc6.0+win2k下測試通過。

3.1、鍊錶初始化

初始化函式用於建立乙個頭結點,由head指向它,該結點的next域為空,data域未設定任何值。由於呼叫該函式時,指標head在本中指向的內容發生改變,為了返回改變的值,形參使用指標型,其時間複雜度為o(1)。

/*初始化單向鍊錶*/

lnode * initlist()

//void initlist(lnode **head)

//

/*初始化單向迴圈函式*/

lnode * initcyclist()

3.2、求單鏈表的長度

單鏈表的長度是指單鏈表中所含結點的個數。此演算法需要從表頭指標出發,沿著每個結點的鏈,每次向下訪問並進行計數,起到最後乙個結點為止,其時間複雜度為o(n)。

/*求單鏈表的長度*/

int lenth(lnode *head)

return len;

}

3.3、從單鏈表中找出關鍵字等於給定值k的結點

從表頭第乙個結點起,依次使每個結點的關鍵字同給定值進行比較,直到某個結點的關鍵字等於給定值k或者查到表尾為止,其時間複雜度為o(n)。

lnode * get(lnode *head,elemtype k)

else

printf("未從鍊錶中找到%d這個元素/n",k);

return null;

}

3.4、在單鏈表中第i個接點之後插入乙個元素為x的新結點

建立乙個data域值為x的新結點*p,然後插入到head所指向的單鏈表的第i個結點之前。若i值超出鍊錶的長度,做「超出範圍處理」 ,其時間複雜度為o(n)。

/*在單鏈表中第i個接點之後插入乙個元素為x的新結點*/

int insert(lnode *head,int i,elemtype x)

if(!p||j!=i-1||i<1)

q=(lnode *)malloc(sizeof(lnode));

q->data=x;

/*生成p節點,x是元素的值*/

q->next=p->next;

p->next=q;

return 1;

}

3.5、刪除元素

線性鍊錶中的元素的刪除要修改被刪元素前驅的指標,**被刪除元素所占用的空間。主要的耗時在查詢上,因而長度為n線性單鏈表進行刪除操作的時間複雜度為o(n)。

/*刪除鍊錶中的元素*/

int del(lnode *head,int i,elemtype x) /*刪除第i個節點,並通過x返回值*/

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

return 0;

q=p->next;

p->next=q->next;

x=q->data;

free(q);

return 1;

}

3.6、已知在乙個陣列a中存放著乙個具有n個元素的線性表,按關鍵字把他們鏈結成乙個帶有附加表頭節點的迴圈單鏈有序表,時間複雜度為o(n2)

void create(lnode *head,elemtype a,int n)

3.7、顯示單向鍊錶中的元素。

/*顯示單鏈表中的所有元素*/

void showlinklist(lnode *head)

if (i==0)

printf("鍊錶中沒有元素/n");

}

3.8、在帶有附加表頭結點的迴圈雙向鍊錶中進行插入和刪除。

3.8.1、儲存結構

typedef int elemtype;

typedef struct nodep,q;

3.8.2、若要在鍊錶中p所指向的結點之後插入乙個q所指向的新結點,則運算步驟為:

q->right=q->right;/*使q結點的右指標指向p結點的後繼指標*/

q->left=p;/*使q結點的左指標指向p結點*/

p->right->left=q;/*使p結點的後繼結點的做指標指向q結點*/

p->right=q;/*使p結點的右指標指向q結點*/

3.8.3、若要刪除指標p所指向的結點,則運算步驟為:

p->left->right=q->right; /*使p結點的前驅結點的右指標指向p的後繼結點*/

p->right->left=p->left; /*使p結點的後繼結點的左指標指向p的前驅結點*/

free(p);

/***p結點*/

3.9

、測試程式

int main()

;

link=initlist();

printf("鍊錶中元素有:%d個/n",lenth(link));

showlinklist(link);

while(1)

printf("請輸入您要插入元素的位置:");

scanf("%d",&i);

if(insert(link,i,x)==0)

break;

}

printf("鍊錶中元素有:%d個/n",lenth(link));

showlinklist(link);

printf("請輸入您所要查詢的元素");

scanf("%d",&x);

get(link,x);

printf("請輸入您所要刪除元素的位置:");

scanf("%d",&i);

if(del(link,i,x))

else

printf("刪除失敗,可能您輸入的下標越界/n");

arraytolink=initcyclist();

create(arraytolink,array,limit);

for(i=0;i

return 1;

}

資料結構與演算法 鍊錶

題目 合併兩個已經排序好的鍊錶 非遞迴和遞迴兩種 方法1 cpp view plain copy print color 000000 合併鍊錶.cpp 定義控制台應用程式的入口點。include stdafx.h include using namespace std struct listnod...

資料結構與演算法 鍊錶

在講述鍊錶之前讓我們對資料結構進行乙個簡單的回顧 我們知道,資料結構指的是描述實際問題中各個資料項節點之間的前後邏輯結構關係,即要麼是線性結構 即某一資料項的前繼節點和後繼節點有且只有乙個 要麼是非線性結構 即某一資料節點的前驅或者後繼節點不止乙個 在確定了實際資料項的資料結構之後,我們要採用某種儲...

資料結構與演算法 鍊錶

反轉鍊錶 def reverse head q none p heap while p temp p.next p.next q q pp temp return p判斷鍊錶環 def meetingnode head if not head return slow head fast head.n...