前言:
寫到快速排序時,之前已經進行了冒泡、選擇、插入排序,發現算法問題很多東西都是和實際問題相逆的,實際你可能會由外及里,由上及下,可是算法里面它有時就需要你由里往外去擴散,好比最里面的是小成果,然后一次次往外變化,成果也慢慢變大,最后直至達到最終成果為止。本篇快速排序方法因為調用了遞歸,你就可以逆着由里及外來思考問題。 寫這篇文章光畫圖就花費了我2小時時間,越抽象就越不好形容和比喻,畫的不好,希望各位不要吐槽。
快速排序:先快速排序將隊列一分為二,然后對每個隊列進行遞歸調用快速排序方法,直至不能再次分解后依次返回成果。
情景描述:
緊接選擇排序情景,有一天,被同學稱為大濕的體育老師胃疼請假休息了,真好數學老師閑着就來代課了,同樣要排列隊形,但是數學老師牛了,說同學們,我今天教你們一種快速排序的方法,到時候來了別忘了教你們的體育老師哦(體育老師估計胃更疼了...)
一、
- 我們就把第一個同學當做基數,其他同學和他進行比較,期間,基數不變,此時基數同學站出來,留下了個空位
- 首先從最后一個同學開開始,依次向前和基數進行比較,第一個比基數同學等高或者矮了,就站到基數的位置,自己的位置又空下了
- 步驟2后,我們再從第一位依次向后和基數比較,如果等於或者比基數高,就站到步驟二留下的空位,自己位置空出來
- 排除前后已經換過位置的同學,重復步驟2和3, 依次和基數比較,然后坐入空位,留下新空位
- 直到都和基數進行比較過,然后基數同學站到最后的空位里面
二、
- 通過步驟一我們把要排列的隊分為了兩隊,而兩隊之內還是高低不齊的
- 首先來排前面的,讓前面的隊依舊以第一個為基數,結尾到分割線同學的前一位,執行步驟一
- 接着排后面的,以分割線同學的后一位為開始,隊列末尾為結束,執行步驟一
- 重復執行步驟2和3,直至不能再拆分即排列完成
步驟一圖解

上圖為一輪快速排序方法
步驟二圖解

上圖為依次遞歸調用快速排序方法,對每次的新隊列進行快速排序
代碼片段
/** * 快速排序,返回一個中軸下標 * @param arr * @param low 隊列起始下標 * @param high 隊列結束下標 * @return */ public int quickSort(int[] arr, int low, int high) { int tmp = arr[low]; // 數組的第一個作為中軸 while (low < high) { while (low < high && arr[high] >= tmp) { high--; } arr[low] = arr[high]; // 比中軸小的記錄移到低端 while (low < high && arr[low] <= tmp) { low++; } arr[high] = arr[low]; // 比中軸大的記錄移到高端 } arr[low] = tmp; // 中軸記錄到尾 return low; // 返回中軸的位置 } /** 遞歸調用快速排序方法,對數組進行排序 **/ public void _quickSort(int[] list, int low, int high) { if (low < high) { int middle = quickSort(list, low, high); // 獲得中軸下標 // 對前部分進行排序,遞歸進行,此時不會執行后半部分,直至不能再次拆分,再依次執行下半部分 _quickSort(list, low, middle - 1); // 對下半部分進行排序 _quickSort(list, middle + 1, high); } }
代碼挺少,但是沒圖的話理解起來太抽象了,還得邊拿筆畫着邊執行着,完了才領悟了其原理。
再來嚴謹的總結下步驟:
- 設置兩個變量i、j,排序開始的時候:i=0,j=N-1
- 從i開始向后搜索,即由前開始向后搜索(i ++ ),找到第一個大於key的A[i],A[i]與A[j]交換
- 從j開始向前搜索,即由后開始向前搜索(j -- ),找到第一個小於key的值A[j],A[i]與A[j]交換
- 從i開始向后搜索,即由前開始向后搜索(i ++ ),找到第一個大於key的A[i],A[i]與A[j]交換
- 重復第3、4、5步,直到 I=J; (3,4步是在程序中沒找到時候j=j-1,i=i+1,直至找到為止。找到並交換的時候i, j指針位置不變。另外當i=j這過程一定正好是i+或j-完成的最后令循環結束
優點:速度快,適合基本無序的隊列
缺點:多個相同的值的相對位置也許會在算法結束時產生變動,所以不穩定,還有借用了遞歸思想,數據大量時消耗內存
終於寫完了,洗洗睡了:) ,最后把這幾天的排序整合下:
寫作不易,難免有疏漏和錯誤,還請慷慨指正,不錯請推薦
ps:歡迎轉載,轉載請注明出處:http://www.cnblogs.com/liuyitian/p/4077624.html
每天多學一點點 代碼少敲一點點
