**:被忽視的 partition 演算法:
首先以無序陣列中的元素為樞軸點 pivot,經過一次遍歷,將陣列中其他元素分為以 pivot 為分界線的兩部分,使得左邊部分的數小於等於pivot,右邊部分的數大於等於pivot(左部分或者右部分都可能為空),最後返回pivot在新的陣列中的位置。
指標單向遍歷
以數列的第乙個元素為軸點,單向遍歷
arr[begin, end)
// do partition in arr[begin, end), with the first element as the pivot.
int partition(vector
&arr, int begin, int end)}}
swap(arr[begin], arr[pos]);
return pos;
}
如果原始陣列為[5,9,2,1,4,7,5,8,3,6],那麼整個處理的過程如下圖所示:
指標雙向遍歷
two pointers 的思想,保持頭尾兩個指標向中間掃瞄,每次在頭部找到大於pivot的值,同時在尾部找到小於pivot的值,然後將它們做乙個交換,就可以一次把這兩個數字放到最終的位置。一種比較明智的寫法如下:
int partition(vector&arr, int
begin, int
end)
arr[begin] = pivot;
return begin;
}
同樣以原始陣列[5,9,2,1,4,7,5,8,3,6]為例,處理流程為:
直觀上來看,賦值操作的次數不多,比前面單向掃瞄的swap次數都少,效率應該會更高。
但是直覺上總是感覺如果將雙向遍歷等同於兩次單向遍歷,效率應該差不多啊。。。
首先用 partition 將陣列分為兩部分,然後分別對左右兩部分遞迴進行快速排序,過程如下:
void quick_sort(vector
&arr, int begin, int end)
int pos = partition(arr, begin, end);
quick_sort(arr, begin, pos);
quick_sort(arr, pos+1, end);
}
首先用 partition 將陣列分為兩部分,得到分界點下標 pos,然後分三種情況:
pos == k-1,則找到第 k 大的值,arr[pos];
pos > k-1,則第 k 大的值在左邊部分的陣列。
pos < k-1,則第 k 大的值在右邊部分的陣列。
int find_kth_number(vector
&arr, int k)
else
if(pos > k-1)
else
}return target_num;
}
問題描述:
給定紅、白、藍三種顏色的小球若干個,將其排成一列,使相同顏色的小球相鄰,三種顏色先後順序為紅,白,藍。
最直接的想法是對紅,藍,白三種顏色的球分別計數,然後根據計數結果來重新放球。
不過如果我們將問題進一步抽象,也就是說將乙個陣列按照某個target值分為三部分,使得左邊部分的值小於 target,中間部分等於 target,右邊部分大於 target,這樣就不能再用簡單的計數來確定排序後的結果。
思想:不斷減少未知區域的元素 當scan指標和bigger指標重合,表示未知區域減小為0, 結束遍歷。
// assume target is in the arr.
void three_way_partition(vector
&arr, int target)
else
if(arr[next_scan_pos] > target)
else}}
Partition演算法詳解
partition演算法有著非常重要的應用,這個演算法的思想雖然簡單,但具體實現的細節卻比較多,今天我重點複習了這個演算法,本文記錄我對這個演算法的理解。二分partition應用 三分partition應用 二分partition 快速排序作為非常著名的排序演算法,其思想卻很簡單 每次從陣列中選乙...
Partition演算法剖析
對,我是來騙訪問量的!o o 二分partition演算法是我們最常使用的,尤其在快速排序中使用最為常見。常見的partition演算法有如下兩種實現思路 演算法思路 int partition vector nums,int begin,int end swap nums pos nums beg...
被忽視的 partition 演算法
如果你學習過演算法,那麼肯定聽說過快速排序的大名,但是對於快速排序中用到的 partition 演算法,你了解的夠多嗎?或許是快速排序太過於光芒四射,使得我們往往會忽視掉同樣重要的 partition 演算法。partition 可不只用在快速排序中,還可以用於 selection algorith...