22王道資料結構P39T24

2021-10-19 13:15:33 字數 2716 閱讀 7024

設計乙個演算法完成以下功能:判斷乙個鍊錶是否有環,如果有,找出環的入口點並返回,否則返回null。

設定快慢兩個指標分別為fast和slow,初始時都指向煉表頭 head。slow每次走一步,即slow=slow->next; fast每次走兩步,即fast=fast->next->next。由於fast 比 slow走得快,如果有環,fast一定會先進入環,而slow後進入環。當兩個指標都進入環後,經過若干次操作後兩個指標定能在環上相遇。這樣就可以判斷乙個鍊錶是否有環。

如下圖所示,當slow剛進入環時,fast早已進入環。因為fast每次比 slow多走一步且fast與slow的距離小於環的長度,所以fast與slow相遇時,slow所走的距離不超過環的長度。

如下圖所示,設頭結點到環的入口點的距離為a,環的入口點沿著環的方向到相遇點的距離為x,環長為r,相遇時fast繞過了n圈。

則有2(a+x)=a+nr+x,即 a=nr-x。顯然從頭結點到環的入口點的距離等於n倍的環長減去環的入口點到相遇點的距離。因此可設定兩個指標,乙個指向 head,乙個指向相遇點,兩個指標同步移動(均為一次走一步),相遇點即為環的入口點。

lnode*

findloopstart

(lnode *head)

if(slow==

null

||fast-

>next==

null

)return

null

;//沒有環,返回null

lnode *p1=head,

*p2=slow;

//分別指向開始點、相遇點

while

(p1!=p2)

return p1;

//返回入口點

}

首先這題的解法非常巧妙了的運用的快慢指標,如果有環的話進行追逐最後相遇。

但是王道這道題給出的**是有問題的,我們編寫如下**進行測試

#include

using

namespace std;

struct lnode

;lnode*

findloopstart

(lnode *head)

if(slow==

null

||fast-

>next==

null

)return

null

;//沒有環,返回null

lnode *p1=head,

*p2=slow;

//分別指向開始點、相遇點

while

(p1!=p2)

return p1;

//返回入口點

}int

main()

r->next=

null;

cout<<

findloopstart

(head)

<

return0;

}

鍊錶中有兩個結點,沒有環,輸出null

鍊錶中有三個結點,沒有環,應該輸出null,但卻死迴圈了

為什麼呢,我們每步輸出slow和fast的位址看一下

第一次slow走一步到0xa11490(第乙個元素結點),fast走兩步到0xa11930(第二個元素結點)

第二次slow走到0xa11930(第二個元素結點),fast應該走到第四個元素結點,但是鍊錶總共只有三個元素,所以fast走到了0(null),我們在看一下迴圈的條件

slow!=null&&fast->next!=null,首先第乙個slow!=nul成立,第二個fast->next!=null這裡就有問題了,因為此時fast已經是空指標,所以執行fast->next這條語句會產生空指標錯誤。

那麼我們下面對程式進行修改

lnode*

findloopstart

(lnode *head)

if(slow==

null

||fast==

null

||fast-

>next==

null

)return

null

;//沒有環,返回null

lnode *p1=head,

*p2=slow;

//分別指向開始點、相遇點

while

(p1!=p2)

return p1;

//返回入口點

}

我們在條件中加入了fast!=null,然後運用邏輯運算子的短路性質,巧妙避免了空指標錯誤。

王道資料結構課後習題 P018

3.長度為l的順序表,編寫乙個時間複雜度為o n 空間複雜度為o 1 的演算法,該演算法刪除線性表中所有值為x的元素。一看就是典型的雙指標問題,於是我寫 如下 for i 0,j i 1 jif a j x else if a i x a i a j 這部分 是有問題的,如果出現在第一位的話就無法解...

王道資料結構課後習題 P37

3 設l為帶頭節點的單鏈表,編寫演算法實現從尾到頭反向輸出每個節點的值。我想到的是reverse一下 笑哭 想想這個就有點殺雞用牛刀的感覺 看了題解說是可以用遞迴 臥槽瞬間orz class solution 利用reverse將整個鍊錶倒置 void reverseoutput listnode ...

王道資料結構課後題 P121

7 判斷乙個二叉樹是否為完全 二叉樹。一開始是想著利用遞迴,判斷有左孩子而無右孩子的節點的個數,並且要求左孩子為葉子節點。判斷的條件很複雜,最後發現這種方法實際上是有問題的。如果同時碰到兩個節點同時為有左葉子節點而右子樹為空,這種情況按照判斷應當返回false 但是這種方法並不能正確返回 1 2 3...