重新上本科 快速排序 中

2021-09-30 16:23:50 字數 1500 閱讀 8149

直接看一下嚴蔚敏的《資料結構》,他是這麼處理的:他利用了錨值位置上的值,參與到交換過程之中。演算法的過程變為:首先,右迭代指示器從右向左遍歷,找到第乙個比錨值小的數值的位置,並將錨值(預設是陣列第乙個元素)與當前位置的數值相交換——此時,右迭代指示器停止,迭代器指向的位置作為臨時變數,存放錨值,該位置向右的序列,即在右迭代器遍歷過的位置上,滿足快速排序的要求(右端的數值比錨值大,左端的數值比錨值小),該位置左側的數值待排序,該位置作為下一次交換的位置;接下來,左迭代指示器從左向右遍歷,(左端迭代器的初始值是錨值的下乙個元素,即陣列的第二個元素),直到遇到第乙個比錨值大的元素,該元素與錨值所在位置元素(右迭代器所指向的位置)進行交換,錨值位置變到左迭代器指向的位置,左迭代器遍歷過的位置上的元素都滿足快速排序需求;接下來,右迭代器繼續向左移動,重複上述的過程,直到兩個迭代器相遇,此時左右迭代器所指的位置就是錨值其時的位置。

這部分**如下:

int elem = array[ilow];

int l = ilow, r = ihigh;

while(l < r)

while(l< r && array[l] <= elem) l++;

if (l < r)

array[r] = elem;

這個過程中,演算法利用了錨值所在的位置,作為臨時變數,進行數值交換;左右迭代器分別找到應該交換的數值的位置,不是相互交換,而是與錨值所在的位置進行交換。這樣,最後迭代器相遇的位置,位置左邊,都是比錨值小的數值;位置右邊都是比錨值大的數值,而迭代器相遇的位置,就是錨值最終應該在的位置。之後,分別對迭代器左右兩端的子串行進行分治求解。完整的演算法如下:

void quicksort2 (int array, int ilow, int ihigh)

while(l< r && array[l] <= elem) l++;

if (l < r)

} // while

array[r] = elem;

// 對子序列遞迴呼叫

quicksort2(ilow,r-1);

quicksort2(r+1,ihigh);

} // if }

這樣**就乾淨了很多。很多老師在講快速排序的時候,側重分治的思想、複雜度的分析等,而在實際中最關鍵的問題「如何將序列分成兩個子串行,滿足快速排序要求」,尤其是以上資料交換的細節,講的不是很細。——其時不怨老師,還是自己不經常實踐。

另外,大家看**,函式最開始的時候都有乙個if判斷,判斷"if(ilow < ihigh)",這個是做什麼的?「防衛性程式設計」,判斷萬一呼叫的時候輸入有錯誤?去掉行麼?後半句對了,但是不是「防衛性程式設計」。快速排序是遞迴演算法,總有乙個終止條件,上面的判斷就是終止條件。當ilow比ihigh大的時候,就說明序列已經有序了,不用進一步遞迴作調整了。

重新上本科 快速排序 下

在我的印象中,絕大多數的教科書講解快速排序的時候,都用嚴蔚敏書中的方法,採用左右兩個迭代指示器,從兩個方向進行遍歷比較。能不能只從乙個方向進行遍歷,遍歷一遍就能完成交換任務呢?演算法導論 提供了一種方法。演算法導論 是從左到右遍歷,設定兩個指示器 從這個角度來說本質上與嚴蔚敏的方法一致 乙個指示器指...

重新上本科 堆排序 上

堆排序很有意思。作為排序演算法來講,它和快速排序都是o nlogn 的時間複雜度,都是就地排序,都是採用遞迴。兩者差不多,既生瑜,何生亮?不過堆是一種很有用的資料結構,通過堆排序演算法,可以學習堆這種資料結構,以後可能用得上。堆排序演算法思路很簡單 第一步,構建乙個堆 第二步,取出堆頂 第三步,如果...

重新上本科 排序 除錯環境

上面列了幾個排序演算法的 這些 都是經過debug,程式驗證過的。我順便也把驗證的環境貼出來吧。很多東西,其實是寫給自己看的。一 隨機數生成程式,生成一定數量的隨機數,用於排序,結果記錄在檔案中。bool generatenum const char sfileout,int icount if i...