您的位置:首页 > 产品设计 > UI/UE

快速排序在Top k问题中的运用(quickSort and quickSelect in Top k)

2018-03-10 16:34 786 查看

参考http://blog.csdn.net/shuxingcq/article/details/75041795

      快速排序算法在数组中选择一个称为主元(pivot)的元素,将数组分为两部分,使得 第一部分中的所有元素都小于或等于主元,而第二部分的所有元素都大于主元。对第一部分递归地应用快速排序算法,然后对第二部分递归地应用快速排序算法。
      在最差情况下,划分由 n 个元素构成的数组需要进行 n 次比较和 n 次移动。因此划分所需时间为 O(n) 。最差情况下,每次主元会将数组划分为一个大的子数组和一个空数组。这个大的子数组的规模是在上次划分的子数组的规模减 1 。该算法需要 (n-1)+(n-2)+…+2+1= O(n^2) 时间。
      在最佳情况下,每次主元将数组划分为规模大致相等的两部分。设 T(n) 表示使用快速排序算法对包含 n 个元素的数组排序所需的时间,因此,和归并排序的分析相似,快速排序的 T(n)= O(nlogn)。

参考https://www.cnblogs.com/en-heng/p/6336625.html

      对于快排在Top k问题中的运用,我们运用Quick Select,Quick Select [1]脱胎于快排(Quick Sort),两个算法的作者都是Hoare,并且思想也非常接近:选取一个基准元素pivot,将数组切分(partition)为两个子数组,比pivot大的扔左子数组,比pivot小的扔右子数组,然后递推地切分子数组。Quick Select不同于Quick Sort的是其没有对每个子数组做切分,而是对目标子数组做切分。其次,Quick Select与Quick Sort一样,是一个不稳定的算法;pivot选取直接影响了算法的好坏,worst case下的时间复杂度达到了O(n2)
O(n2)
Quick Select的目标是找出第k大元素,所以
若切分后的左子数组的长度 > k,则第k大元素必出现在左子数组中;
若切分后的左子数组的长度 = k-1,则第k大元素为pivot;
若上述两个条件均不满足,则第k大元素必出现在右子数组中。

下面贴上JAVA代码:import java.util.ArrayList;

public class QuickSort {
//存放最大的k个数
public ArrayList<Integer> result = new ArrayList<Integer>();

public int partition(int[] a,int low,int high){
int privotKey = a[low];
while (low < high){
while (low < high && a[high] >= privotKey){
high --;
}
// swap(a[high],a[low]);
int temp = a[high];
a[high] = a[low];
a[low] = temp;

while (low < high && a[low] <= privotKey ){
low ++;
}
// swap(a[low],a[high]);
temp = a[low];
a[low] = a[high];
a[high] = temp;
}
// for (int b:a) {
// System.out.print(b + " ");
// }
// System.out.println("");
//此时,low = high
// low的位置是基准数的下标
return low;
}

//快排
public void quickSort(int[] a,int low,int high){
if (low < high){
int privotLoc = partition(a,low,high);
quickSort(a,low,privotLoc - 1);
quickSort(a,privotLoc + 1,high);
}
}

//找第k个最大的元素
public int findKthLargest(int[] nums, int k) {
return quickSelect(nums, k, 0, nums.length - 1);
}

// 快速选择找第k个最大的元素
public int quickSelect(int[] arr, int k, int left, int right) {
// if (left == right) return arr[right];
int index = partition(arr, left, right);
if (right - index + 1 > k){
return quickSelect(arr, k, index + 1, right);
}
else if (right - index + 1 == k){
for (int i = index; i <= arr.length - 1; i++) {
result.add(arr[i]);
}
return arr[index];
}
else{
return quickSele
4000
ct(arr, k - right + index - 1, left, index - 1);
}
}

public static void main(String[] args){
int [] a ={47,25,16,24,15,23,1548,255,445,47,54,0,99999,2312213,1223123123,2};
QuickSort quickSort = new QuickSort();
int num = quickSort.findKthLargest(a,3);
// System.out.println(num);
for (Integer i:quickSort.result) {
System.out.println(i);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JAVA