排序演算法雜談(四) 快速排序的非遞迴實現

2022-06-05 18:09:07 字數 1302 閱讀 1408

1. 前提

排序演算法(七) —— 快速排序

排序演算法雜談(三) —— 歸併排序的非遞迴實現

2. 快速排序與歸併排序的遞迴

快速排序(quick sort)與歸併排序(merge sort)雖然都採用了遞迴地思想,但是其遞迴地本質卻有所不同。

快速排序,是先通過劃分(partition)演算法,將陣列兩分,劃分的過程中,比主元(pivot)小的數字全部被劃分到了左側,比主元大的數字全部被劃分到了右側。

然後對兩分的陣列進行遞迴。當陣列兩側的長度均小於等於1,那麼陣列就自然有序了。

歸併排序,是將原陣列二等分,直到被等分的陣列長度小於等於1,那麼被等分的陣列就有序了,然後對這等分的陣列進行合併。

所以說,快速排序與歸併排序,正好代表了遞迴的兩種典型,如果將遞迴的過程看做是一顆二叉樹,那麼:

3. 快速排序非遞迴實現的堆疊模型 stack 與 記錄模型 record

快速排序這種,優先操作,然後遞迴的特點,大大簡化了構造目標堆疊模型的難度。

在歸併排序中,不難發現,其構造目標堆疊模型的過程,是不斷入棧的過程,最後一次性地處理堆疊資訊。

相反,在快速排序中,目標堆疊是乙個不斷 入棧-出棧 的過程,在出棧的過程中,就對資料進行處理,沒有必要再最後一次性處理。

而且,由於劃分具有不穩定性,所以沒有辦法給出確切的堆疊模型。

快速排序的遞迴過程,只需要關心其左邊與右邊的座標:

private static class record 

}

4. 快速排序非遞迴的過程

快速排序非遞迴的執行過程中,只需要乙個堆疊空間,其執行過程如下:

於是,有如下**:

public final class quicksortloop extends basicquicksort 

if (pivot + 1 <= right)

while (!stack.isempty())

if (pivot + 1 <= record.right) }}

}private static class record

}}

如果 record 模型過於簡單,可以直接通過入棧-出棧 具體的資料來簡化這個過程。

5. 關於遞迴轉迴圈需要知道的事情

通過歸併排序和快速排序非遞迴實現的講解,似乎將其轉化為迴圈是乙個更佳的做法,其實不然,它只適用於特定的場景。

關於這種方法,需要有如下的認知:

演算法 排序(四)快速排序

快速排序 對氣泡排序的一種改進 1 時間複雜度o nlogn o n2 2 空間複雜度o logn o n 排序排序需要棧空間實現遞迴 3 不穩定的 4 快速排序的思想 帶排序列經過一次快排劃分,可以得到 子串行5 遞迴實現void qsort int l,int low,int high 用if ...

PHP 排序演算法(四) 快速排序

快速排序 思路 我們首先要找到乙個基準,陣列的前半部分是比基準小的元素,陣列後半部分是比基準大的元素,這裡我就拿陣列第乙個元素作為基準 設定隊首和隊尾兩個指標 隊尾指標先進行活動,一直向隊首移動,直到找到比基準值小的元素,然後將這個值賦給隊首指標處 下面隊首指標開始活動,一直向隊尾移動,直到找到比基...

演算法系列 排序演算法(四)快速排序

快速排序是通過兩個指標相互交換完成一次快速排序,類似於遞迴的二分排序,從交換上來講比較像冒泡 為什麼這麼說呢?不管是插入還是直接,都需要在移動之前遍歷元素 冒泡直接比較交換。公升序 資料 4251 376下標 0123 4561 指標1 4 指標2 6 指標1是用來二分的標準,指標2是被二分的元素,...