鍊錶 常規操作

2021-09-11 18:48:51 字數 3604 閱讀 3915

單鏈表反轉

方法一:

考慮如何將乙個單鏈表反轉,一開始的靈感是由頭插法建立單鏈表演算法而來的,即事先建立乙個空的單鏈表,在遍歷單鏈表的同時,不斷的將結點從頭插入到空煉表中,這樣一來,就建立出了單鏈表的反轉鍊錶。

演算法思路:

時間複雜度o(n),空間複雜度o(n)

具體實現**如下:

list list;                    // 已知鍊錶list

list new_list; // 新建空鍊錶new_list

node *p = list.head();

node *q = new_list.head();

while (p->next != null) // 遍歷鍊錶list

這樣便得到了新的鍊錶new_list,即原鍊錶list的反轉鍊錶。

方法二:

在頭插法建立新鍊錶的基礎上,設計出在鍊錶本身上進行的原地反轉演算法。

演算法思路:

時間複雜度o(n),空間複雜度o(1)

具體實現**如下:

void mylist::reverselist()

}

兩個有序的鍊錶合併

首先我們分析兩個有序鍊錶,這裡舉例 list1 = , list2 = 。其中phead1phead2分別指向兩個鍊錶的首結點,接著我們分析兩個鍊錶合併後的頭指標pmergedhead,通過比較兩個鍊錶的頭結點的data值可知,list1鍊錶的頭結點data值小於list2的頭結點data值,因此確定出合併後鍊錶的頭指標為phead1。緊接著確定list1的子鍊錶與list2鍊錶合併後的頭指標,依次遞迴,直至兩個鍊錶中任意鍊錶為空。

因此總結出遞迴演算法的思路:

由於每次遞迴都會使得兩條鍊錶中的一條減少乙個結點,因此當某條鍊錶為空時,會返回另一條鍊錶的頭結點,此時到達遞迴的基準情形

時間複雜度o(min(m, n)),空間複雜度o(min(m, n))

具體**實現如下:

node* merge(node* phead1, node* phead2)

else

return pmergedhead;

}

快慢指標的應用

由於快慢指標在鍊錶的一些操作中有很大的幫助,這裡先介紹一下快慢指標的概念。

快慢指標中的快慢指的是移動的步長,即每次向前移動速度的快慢。例如可以讓快指標每次沿鍊錶向前移動2,慢指標每次向前移動1次。我們在鍊錶的某些操作時,可以定義兩個指標來遍歷鍊錶,通過使兩個指標的移動速度不同,來使操作變得更加簡單。

快慢指標應用(一):判斷鍊錶是否存在環

如果鍊錶存在環,就好像操場的跑道是乙個環形一樣。此時讓快慢指標都從煉表頭開始遍歷,快指標每次向前移動兩個位置,慢指標每次向前移動乙個位置;如果快指標到達null,說明鍊錶以null為結尾,沒有環。如果快指標追上慢指標,則表示有環。

時間複雜度o(n),空間複雜度o(1)

具體**實現如下:

bool hascircle(node *head)

return false;

}

快慢指標應用(二):判斷鍊錶是否存在環,如果存在,找到環入口

之前已經介紹了如何判斷鍊錶是否存在環,接下來分析如果鍊錶存在環,如何找到環的入口點?

當fast若與slow相遇時,slow肯定沒有走遍歷完鍊錶或者恰好遍歷一圈。於是我們從煉表頭與相遇點分別設乙個指標,每次各走一步,兩個指標必定相遇,且相遇第一點為環入口點。(這裡有必要給出**解釋,以後會補充)

時間複雜度o(n),空間複雜度o(1)

具體**實現如下:

node* findloopport(node *head) 

}if ((fast == null) || (fast->next == null)) // 鍊錶不存在環

// 第二步:尋找環的入口點

slow = head; // 讓slow回到鍊錶的起點,fast留在相遇點

while (slow != fast) // 當slow和fast再次相遇時,那個點就是環的入口點

return slow;

}

刪除鍊錶中倒數第n個結點

可以定義兩個指標,第乙個指標從鍊錶的頭指標開始遍歷向前走k-1步,第二個指標保持不動;從第k步開始,第二個指標也開始從鍊錶的頭指標開始遍歷。由於兩個指標的距離保持在k-1,當第乙個指標到達鍊錶的尾節點時候,第二個指標正好是倒數第k個節點。

時間複雜度o(n),空間複雜度o(1)

具體**實現如下:

bool rdelete_n(node *phead, unsigned n)      // 函式名前面的r代表反向  

while (pahead->next != null) // 前後兩個指標一起向前走,直到前面的指標指向尾結點

// 此時指標prebehind指向倒數第n個結點的前繼結點

// 開始刪除操作

node *pbehind = prebehind->next;

prebehind->next = pbehind->next;

delete pbehind;

return true;

}

求鍊錶的中間結點

令慢指標每次移動乙個位置,而快指標每次移動兩個位置,由於快指標移動速度是慢指標的兩倍,所以當慢指標指向鍊錶尾結點時,慢指標剛好走到鍊錶的中間。但是根據鍊錶結點的個數要進行分類討論(下面討論以鍊錶不存在頭結點為前提):

此時快指標走到尾結點為終止條件,直接返回慢指標即可。

此時快指標達到倒數第二個結點為終止條件,我們這裡選擇返回鍊錶中間兩個結點的前面那個。

時間複雜度o(n),空間複雜度o(1)

具體**實現如下:

node* getmiddle(node *head)

}}

js 實現鍊錶的常規操作

建立乙個鍊錶 建立乙個鍊錶的節點,每乙個鍊錶都是跟節點 param value constructor function node value let a newnode a let b newnode b let c newnode c let d newnode d let w newnode ...

oracle常規操作

1 建立表 sql create table test id varchar2 10 age number 2 備份表 sql create table asselect from test group by id 3 刪除表 sql drop table test 刪除表結構和表資料 4 清空表 ...

ROS常規操作

記錄下在使用ros的過程中,一些常用操作。在ros中如果使用乙個工作空間,直接在 bashrc檔案的最後一行加入 source hellow catkin ws devel setup.bash 就可以讓roscd找到工作空間中的包了。但是如果使用多個工作空間,直接在 bashrc 中再加一句話 s...