减治法在查找算法中的应用(JAVA)--快速查找
減治法在查找算法中的應用
快速查找:選擇問題是求一個n個數列表的第k個最小元素的問題,這個數k被稱為順序統計量。對于k=1或k=n來說,這并沒有什么意義,我們通常會要找出這樣的元素:該元素比列表中一半元素大,比另一半元素小,這樣的元素被稱為中值。我們當然可以對列表進行排序,之后找出對應下標的值,但是!!!這樣一個查找問題,反而要對整個列表排序,是不是有點多余了呢?
這里引入劃分的概念我們可以標定一個樞軸(任意元素,一般為首個元素),使得左半部分元素均小于樞軸,右半部分均大于樞軸。劃分的方法由兩種,Lomuto劃分和Hoare劃分。這里僅介紹Lomuto。
我們假設有一個數組a[0, n-1],其子數組為a[l, r](0 <= l <= r <= n-1),假定首個元素為樞軸p,將該數組分為三段,順序放在p之后,依次為,第一段[元素小于p],第二段[元素大于等于p],第三段[尚未處理元素]。算法開始時前兩段均為空。
從i = l+1開始,從左到右掃描子數組a[l, r],將第三段的首個元素與p比較,若a[i]>=p,執行i+1,這就相當于將a[i]劃入了第二段,同時縮小了第三段;若a[i]<p,需要將s+1(s始終指向第一段的末位元素),同時交換a[i]與a[s],之后i+1。直到第三段為空,交換a[p]與a[s]。
下圖為Lomuto劃分示意圖:
熟悉快速排序的讀者估計看出來了,這就是快速排序中的一部分函數,只不過沒有接觸過Lomuto這種叫法而已。
當然,我們這里使用的方法就是快速選擇(“快速”這一方法一開始并非用于排序,而是查找),下面給出查找第k小元素的代碼:
public class Main {static int[] a= {89, 45, 68, 90, 29, 34, 17};static int k = 2;public static void main(String[] args) {System.out.println(fastsort(0, a.length-1, k));for (int i = 0; i < a.length; i++) {System.out.print(a[i] + " ");}}private static int Lomuto(int l, int r) {int p = a[l];int s = l;for (int i = l+1; i <= r; i++) {if (a[i] < p) {s = s+1;int temp = a[s];a[s] = a[i];a[i] = temp;}}int temp = a[l];a[l] = a[s];a[s] = temp;return s;}private static int fastsort(int l, int r, int k) {int s = Lomuto(l, r);/*** s在劃分之后變成了樞軸所在的位置下標,如果s=k,輸出a[s]* 這里要寫成l+k-1,如果劃分到右側,只寫k會出問題* */if (s == l + k - 1) {return a[s];}else if (s > l + k - 1){return fastsort(l, s-1, k);} else {return fastsort(s+1, r, l+k-1-s);}} } 不幸的是,這樣的算法時間復雜度為O(n^2),比之前基于排序的方法實際上更糟糕,但是分析表明,這種方法的平均情況下效率是線性的。而且基于劃分的算法不僅可以查找第k小的元素,還可以給出列表中k個最小元素和n-k個最大元素。
總結
以上是生活随笔為你收集整理的减治法在查找算法中的应用(JAVA)--快速查找的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Log4j简单记录
- 下一篇: linux部署redis详细步骤