最近看了一篇文章,介紹遞歸轉非遞歸的方法,主要是通過stack的數據結構模擬遞歸函數堆棧的層次調用(後進先出,最裏層–>最外層,層層彈出),排序算法很多是通過遞歸來實現的,這裏照葫蘆畫瓢,實現一下非遞歸的快排算法。
先附上快排的遞歸用法,用於對比
/* 快速排序:從數組中選出一個值flag,通過一輪比較,將比flag大的置於一側,比flag小的置於另一側,再依照此法,對這兩部分做同樣的比較 */
/* 複雜度:最壞情況,每次選取flag爲最大或最小元素,退化成線性比較,O(n^2)
最好情況,每次選取的flag爲中間值時,類似平衡樹,每次都對半分,性能爲O(nlogn) */
void Test_Init::quickSort(std::vector<int>& sortArray, int begin, int end)
{
if (begin >= end)
{
return;
}
int i = begin;
int j = end;
int flag = sortArray[j];//標誌位,以flag爲界限,大於flag置於右邊,小於flag的置於左邊
while(i < j)
{
while ((sortArray[i] <= flag) && ((i < j)))
{
i++;
}
sortArray[j] = sortArray[i];
while((sortArray[j] >= flag)&& (i < j))
{
j--;
}
sortArray[i] = sortArray[j];
}
sortArray[i]=flag;
/* 經過一輪比較,以flag爲界限,分爲左右兩邊,左邊比flag小,右邊比flag大然後遞歸進行下一輪比較 */
quickSort(sortArray, begin, i - 1);
quickSort(sortArray, i + 1, end);
}
再看一下非遞歸的寫法
void Test_Init::quickSortNoRecursive(std::vector<int>& sortArray)
{
struct SnapShot
{
int start;
int end;
};
SnapShot shot;
shot.start = 0;
shot.end = sortArray.size() - 1;
std::stack<SnapShot> shotStack;
shotStack.push(shot);
while(!shotStack.empty())
{
/* 每次彈出棧頂元素 */
SnapShot cur = shotStack.top();
shotStack.pop();
if (cur.start >= cur.end)
{
/* 僅有一個元素時,不必比較 */
continue;
}
int i = cur.start;
int j = cur.end;
int flag = sortArray[j];
while(i < j)
{
while ((sortArray[i] <= flag) && ((i < j)))
{
i++;
}
sortArray[j] = sortArray[i];
while((sortArray[j] >= flag)&& (i < j))
{
j--;
}
sortArray[i] = sortArray[j];
}
/* flag右側進棧 */
sortArray[i]=flag;
int tmp = cur.start;
cur.start = j + 1;
shotStack.push(cur);
/* flag左側進棧,先出 */
SnapShot next;
next.end = j - 1;
next.start = tmp;
shotStack.push(next);
}
return;
}