直奔主題,世界上「最漂亮」的排序算法。前端
void stooge_sort(int arr[], int i, int j){ if (arr[i]>arr[j]) swap(arr[i], arr[j]); if (i+1>=j) return; int k=(j-i+1)/3; stooge_sort(arr, i, j-k); stooge_sort(arr, i+k, j); stooge_sort(arr, i, j-k); }
《算法導論》習題中的「完美排序」,由Howard、Fine等幾個教授提出,之因此稱爲「完美排序」,是由於其代碼實現,優雅、工整、漂亮。面試
代碼不是很好理解,一步步講解下思路。
首先,排序傳入的參數是待排序的數組arr[i, j];
算法
第一步:比較i與j位置的元素,根據排序規則決定是否進行置換。
畫外音:本栗子,假設排序規則是從小到大。
置換完成後,判斷排序是否結束,當i和j相鄰時,排序結束。後端
第二步:將arr[i, j]三等分;
畫外音:總元素個數是j-i+1。數組
第三步:遞歸arr的前2/3半區。
架構
第四步:遞歸arr的後2/3半區。ide
第五步:遞歸arr的前2/3半區。code
排序結束。blog
再看一遍,印象深入不?排序
void stooge_sort(int arr[], int i, int j){ if (arr[i]>arr[j]) swap(arr[i], arr[j]); // 比較 if (i+1>=j) return; // 是否結束 int k=(j-i+1)/3; // 三等分 stooge_sort(arr, i, j-k); // 前2/3半區 stooge_sort(arr, i+k, j); // 後2/3半區 stooge_sort(arr, i, j-k); // 前2/3半區 }
然並卵,除了代碼好看,完美排序毛用沒有,由於它是一個挺慢的算法。
由代碼很容易看出來:
(1)當只有1個元素時,完美排序的時間也是1;
(2)當有n個元素時,完美排序由一個常數計算,加上三次遞歸,每次遞歸數據量爲(2/3)*n;
即,其時間複雜度遞歸式爲:
T(1) = 1;
T(n) = 3T(2/3n) + 1;
使用《搞定全部時間複雜度計算》中的遞歸式計算方法,最終獲得,完美排序的時間複雜度是O(n^2.7),比O(n^2)的排序都要慢。
完美排序的排序證實,不在文章中展開。從代碼直觀能感覺到,經過swap和三次遞歸,趨勢上,小的元素會往前端走,大的元素會日後端走,直至完成排序。
畫外音:快速排序的過程是partition+兩次遞歸,也是小的元素往前端走,大的元素日後端走,直至完成排序。
但願這一分鐘,你們有收穫。
架構師之路-分享可落地的技術文章
推薦閱讀:
《TopK與快速排序深度解析》
《搞定全部時間複雜度計算》
《拜託,面試別再問我基數排序了!》
《拜託,面試別再問我計數排序了!》
《拜託,面試別再問我桶排序了!》
做業:在本身的電腦上,實現6行的完美排序,從此面試手寫排序再也不是問題。