鍊錶操作練習

2021-08-28 12:01:30 字數 4488 閱讀 3942

本小題請務必重視,綜合了各種鍊錶操作(各種考試考題),可以做成乙個比較完整的工程,請設計測試程式進行測試,務必自己編寫**。

1.針對帶表頭結點的單鏈表,試編寫下列函式。

(1) 建立函式create:根據一維陣列a[n]建立乙個單鏈表,使單鏈表中各元素的次序與a[n]中各元素的次序相同,要求該程式的時間複雜性為o(n)。

(2) 定位函式locate:在單鏈表中尋找第i個結點。若找到,則函式返回第i個結點的位址;若找不到,則函式返回null。

(3) 求最大值函式max:通過一趟遍歷在單鏈表中確定值最大的結點。

(4) 統計函式number:統計單鏈表中具有給定值x的所有元素。

(5) 倒置函式reverse: 倒置線性表中元素的順序。

(6) 整理函式tidyup:在非遞減有序的單鏈表中刪除值相同的多餘結點。

(7) 合併兩個鍊錶mergelists: 輸入的鍊錶按照其元素順序從小到大排序,輸出的鍊錶也要求按照元素的大小順序排列。

注:認真完成上面的題目可以快速入門鍊錶操作。本文給出的**示例是博主的課堂練習,只考慮了相關功能的實現,有些細節的處理不夠完善,不建議讀者直接複製使用,希望讀者閱讀過程中思考這些問題。

先來分析一下這個題目涉及的鍊錶操作技術:

create/mergelists((末尾)插入

locate/max/number(遍歷

reversetidyup(刪除

可以看出,這七個題涉及的操作無非是線性表的增刪查改,附上**:

#include

using namespace std;

template class link

link

(link* nextval =

null)}

;template

void

lprint

(link

*l) cout <<

">"

<< endl;

}template

link

*create

(e *a,

int n)

return head;

}template

link

*locate

(link

*head,

const

int index)

return

null;}

template

link

*max

(link

*head)

return temp;

}template

intnumber

(link

*head,

const e& value)

return num;

}template

void

reverse

(link

*head)

curr->next = pre;

head->next = curr;}}

template

void

tidyup

(link

*head)}}

template

void

listmerge

(link

*head1, link

* head2, link

*head3)

else

curr3 = curr3->next;}if

(curr1 !=

null

) curr3->next = curr1;

if(curr2 !=

null

) curr3->next = curr2;

}int

main()

;int b=

;int c=

; link<

int>

*p =

create

(a,10);

lprint

(p);

link<

int>

*p1 =

locate

(p,11);

if(p1 !=

null

) cout << p1->element << endl;

link<

int>

*p2 =

max(p);if

(p2 !=

null

) cout << p2->element << endl;

cout <<

"the total number of 32 is "

<<

number

(p,32

)<< endl;

reverse

(p);

lprint

(p);

tidyup

(p);

lprint

(p);

p =create

(b,10);

p1 =

create

(c,10);

link<

int>

*p5 = new link<

int>

;listmerge

(p, p1, p5)

;lprint

(p5)

;system

("pause");

}

注:這裡不得不提一下,第6題讀者只需將它當做當做remove函式練習即可,它並不能真正意義上實現tidyup,只是本示例**為了達到這種效果,故意湊了乙個陣列。

實現鍊錶倒置的思路很簡單,只需將當前結點curr的next指標修改為指向當前結點的前乙個結點即可。

由於單鏈表每個結點只能儲存下乙個結點的位址,而不知道上乙個結點的位址,所以我們需要乙個指標pre儲存當前結點前乙個指標的位址。

但是只用兩個指標是無法完成整個鍊錶的倒置的,當我們將curr->next修改為pre後,我們就丟失了原來curr->next中儲存的當前結點的下乙個結點的位址,這樣就無法遍歷後面的鍊錶了。

所以在修改curr->next之前,我們需要使用post指標將當前結點的下乙個結點的位址儲存下來。當完成curr->next指標的修改後,我們就將當前位置向後移動乙個結點,即將curr指標指向post。相應的依次維護prepost指標完成鍊錶的遍歷。

博主比較懶,不想繪圖,就在網上找了乙個鍊錶轉置操作的**。

//鍊錶轉置

template

void

reverse

(link

*head)

curr->next = pre;

head->next = curr;

}}

下面我們來看mergelists函式,有點演算法基礎的讀者可以一眼看出,這個函式就是歸併排序(mergesort)的合併操作。具體思路是:對於兩個有序的線性表a和b,每次將a和b中最小的元素從原表中『刪除』,放入空線性表c中。因為a和b原先就是有序遞增的,a和b中的第乙個元素分別是a和b表中的最小值,所以找a和b中所有元素的最小值就可以轉化為比較a和b表中第乙個元素的大小,較小的那乙個即為所有元素的最小值。重複上述過程直到a或b中有乙個表為空,此時,還未空的那乙個表的剩餘元素均大於表c中的元素且是有序的,我們只要將這些元素全部複製到表c中即可。

template 

void

listmerge

(link

*head1, link

* head2, link

*head3)

else

curr3 = curr3->next;}if

(curr1 !=

null

)//由於是鍊錶,我們只需將指標指向修改一下即完成'元素複製'

curr3->next = curr1;

if(curr2 !=

null

) curr3->next = curr2;

}

同樣,附上歸併排序**。

ps:如果讀者對於線性表adt以及c++模板不熟悉的可以參考博主的另一篇博文

線性表(一) 從線性表adt到鍊錶。裡面還有鍊錶insert操作的**。

鍊錶操作練習

這裡來總結一下覺得比較有思想的題啪 160.相交鍊錶 這裡的想法是a b與b a遍歷的時間是一樣的,就是說從a鍊錶開始遍歷接著從b鍊錶開始遍歷與先遍歷b在遍歷a同時結束。public class solution pa pa.next pb pb.next return ans 206.反轉鍊錶 這...

鍊錶常見操作練習

鍊錶是乙個很重要的資料結構,一直沒有好好的寫過練習,這次放假,好好練習一下。1 定義鍊錶節點 include include include typedef struct int node node 2 合併兩個有序鍊錶 版本1 node merge node p,node q else while...

棧的操作練習(鍊錶)

用鍊錶來模擬棧,節點需要乙個指向前乙個節點的pre域和資料域 棧只需要乙個棧頂即可 public class nodestack 判斷棧為空的操作就是判斷棧頂是否為null 前面初始化的棧頂就是為null 判斷是否為空 鍊錶入棧就是將入棧的節點pre域指向當前的棧頂,然後再將棧頂移到新壓入棧中的節點...