本例中使用的單鏈表庫是自己編寫的,在前面博文中有提到過:
http://blog.csdn.net/lvjing2/article/details/14045011
這次關於單鏈表的算法,就是引用這個庫進行實現的,所以如果需要測試本算法,就需要拷貝下前文中的代碼了。好了,廢話不多說了。
算法要求:
輸入一個單鏈表,輸出該鏈表倒數第i個結點。鏈表的倒數第0個結點爲該鏈表的尾指針。
算法分析:
1. 最容易想到的是,先走到鏈表的尾結點,然後回溯到倒數第i個結點。但是算法要求中的是單向鏈表,故指針是無法從後往前的。
2. 既然無法從後往前,那可以遍歷整個鏈表求出整個鏈表的長度n,然後就可知道,倒數第i個結點就是第n-i-1個結點。然後再從頭結點走到地n-i-1個結點,從而找到該結點。
但這樣需要遍歷鏈表兩次,第一次得到鏈表結點個數n,第二次得到從頭結點開始的第n-i-1個結點,即倒數第i個結點。如果結點不多,這是一種可行的方法。但當結點很多時,有可能不 能一次性把整個鏈表從硬盤讀入內存,那麼兩次遍歷結點就意味着需要兩次從硬盤讀入到物理內存,而這樣的時間消耗是非常大的。所以我們還將尋找更好的方法來更好地解決這個問題。
3. 下面介紹的是隻通過一次遍歷找到倒數第i個結點的方法。
a. 定義兩個指針:p1, p2.初始化兩個指針都指向頭結點。
b. p1指針開始遍歷,p2保持不動。
c. 當p1遍歷到第i個結點後,p2開始遍歷。(這樣p1和p2指針的距離永遠保持i個結點的距離)
d. 當p1遍歷到鏈表尾指針時,返回p2.
算法代碼(可在anycodes在線編譯測試):
position FindFromLast(list L, int indexRev)
{
position p1 = L, p2 = L;
int i1 = 0;
while(p1->next)
{
i1++;
p1 = p1->next;
if(i1 > indexRev)
{
p2 = p2->next;
}
}
return p2;
}