利用快速排序找到第k大的数字
来源:互联网 发布:西北师大知行学院分布 编辑:程序博客网 时间:2024/05/17 22:06
概念及本文参考
快速排序 - 维基百科英文
快速排序 - 维基百科中文
具体思路及代码
快排的思路就是把数字分成两边,小的放左边,大的放右边,相等的要么都放左边要么都放右边。
找到第k大的元素就是:根据快排分区得到的主元下标比k大还是比k小,再对其中一边进行快排查找直到得到的主元下标等于k。
- 快排基本版
我这里是以最右边的元素为基准,从左往右找大于基准的数字和从右往左找小于或等于基准的数字并进行交换,直到左右两个的下标相遇(相等),就返回这个下标。需要O(n)的存储空间。
int partition1(int *arr, int left, int right) { int pivot = arr[right]; int low = left, high = right - 1; while (low < high) { while (low < high && arr[low] <= pivot) ++low; while (high > low && arr[high] > pivot) --high; if (low < high) swap(&arr[low], &arr[high]); } // 把主元放进一个合适的地方并返回主元下标 if (arr[high] > pivot) { swap(&arr[high], &arr[right]); return high; } else { swap(&arr[high + 1], &arr[right]); return high + 1; }}
快排优化版
这个版本又叫原地(in-place)分区。暂时地把基准放在数字最后面,最后再交换回中间。空间复杂度O(logn)。
// 以主元为中心划分:左边<=右边>;返回主元下标// 原地分区(in-place)算法int partition(int *arr, int left, int right) { int pivot = arr[right]; // 取最后一个元素为主元 int large_num_index = left; // 找到第一个一个大于pivot值的元素下标 while (arr[large_num_index] <= pivot && large_num_index < right) ++large_num_index; // 与large_num_index后第一个小于pivot的值进行交换 for (int i = large_num_index + 1; i < right; i++) if (arr[i] < pivot) swap(&arr[i], &arr[large_num_index++]); // 把主元元素交换到中间位置并作为一个分隔的标志 swap(&arr[right], &arr[large_num_index]); return large_num_index;}
测试代码
- 对两种快排算法的测试
#include <iostream>#include <cstdio>#include <cstdlib>#include <ctime>using namespace std;#define ARRAYSIZE 100 #define MAX_NUM 65536#define MIN_NUM -1#define TRUE 1#define FALSE 0void swap(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp;}// 打印出数组void print_array(int arr[], int num) { for (int i = 0; i < num; i++) cout << arr[i] << " "; cout << endl;}// 递归快排void quicksort(int *arr, int left, int right) { if (left < right) { int pivot_index = partition(arr, left, right); quicksort(arr, left, pivot_index - 1); quicksort(arr, pivot_index + 1, right); }}void quicksort1(int *arr, int left, int right) { if (left < right) { int pivot_index = partition1(arr, left, right); quicksort1(arr, left, pivot_index - 1); quicksort1(arr, pivot_index + 1, right); }}// 复制数组void copy_array(int *copyarr, int *arr, int num) { for (int i = 0; i < num; i++) copyarr[i] = arr[i];}// 比较两个数组内容是否相同int comp_array(int *arr, int *copyarr, int num) { for (int i = 0; i < num; i++) if (copyarr[i] != arr[i]) return FALSE; return TRUE;}void quicksort_test() { srand((unsigned)time(NULL)); int arr[ARRAYSIZE] = {0}; int copyarr[ARRAYSIZE] = {0}; for (int i = 0; i < ARRAYSIZE; i++) arr[i] = rand(); copy_array(copyarr, arr, ARRAYSIZE); print_array(arr, ARRAYSIZE); quicksort(arr, 0, ARRAYSIZE - 1); quicksort1(copyarr, 0, ARRAYSIZE - 1); cout << endl; print_array(arr, ARRAYSIZE); print_array(copyarr, ARRAYSIZE); if (comp_array(copyarr, arr, ARRAYSIZE)) cout << "Correct" << endl; else cout << "Error" << endl;}int main() { quicksort_test();}
测试结果可知这两种快排得出的结果一致。
- 对查找第K大元素的测试
int find_kth_element(int *arr, int left, int right, int k) { if (left <= right) { int pivot_index = partition(arr, left, right); if (pivot_index == k) return arr[pivot_index]; else if (pivot_index < k) return find_kth_element(arr, pivot_index + 1, right, k); else return find_kth_element(arr, left, pivot_index - 1, k); } return -1;}int find_kth_element1(int *arr, int left, int right, int k) { if (left <= right) { int pivot_index = partition1(arr, left, right); if (pivot_index == k) return arr[pivot_index]; else if (pivot_index < k) return find_kth_element1(arr, pivot_index + 1, right, k); else return find_kth_element1(arr, left, pivot_index - 1, k); } return -1;}// 升序int compare(const void *a, const void *b) { return (*(int *)a - *(int *)b);}void find_kth_element_test() { srand((unsigned)time(NULL)); int arr[ARRAYSIZE] = {0}; int copyarr[ARRAYSIZE] = {0}; int examarr[ARRAYSIZE] = {0}; for (int i = 0; i < ARRAYSIZE; i++) arr[i] = rand(); copy_array(copyarr, arr, ARRAYSIZE); copy_array(examarr, arr, ARRAYSIZE); print_array(arr, ARRAYSIZE); int k = ARRAYSIZE / 2; cout << find_kth_element(arr, 0, ARRAYSIZE - 1, k) << endl; cout << find_kth_element1(copyarr, 0, ARRAYSIZE - 1, k) << endl; // 用stdlib自带的qsort进行验证 qsort(examarr, ARRAYSIZE, sizeof(int), compare); cout << examarr[k] << endl;}int main() { find_kth_element_test();}
测试结果是三种方法得出的数字都是一致的~
记得去年也做过这道题,当时我还写了很久,嗯,现在用的时间也很久QAQ
阅读全文
0 0
- 利用快速排序找到第k大的数字
- 利用快速排序思想求数组第k大元素
- 快速排序以及找到第k小的元素
- 两个排序的数组,找到第k大的元素
- 不排序找到第k大的值
- 利用快速排序思想找出数组中第K大的数
- 快速找出第K大的元素 (快速排序)
- 寻找第k小的数字,包括快速排序
- 分治算法的利用例子(查找最大最小数,快速排序,查看第k小的数字)
- 第k大的数(快速排序的划分过程)
- 由快速排序引出的第k大的数..
- 快速排序找第k大的数
- 快速找到前m大的数字。
- 求n个数中第k大的数、前K大的数、快速排序
- 【滴滴笔试】利用快排找到一个无序的数组中的第K大的数
- LeetCode--找到两个排序数组中第k大的元素
- (1)冒泡法排序代码(另一个应用是找到第K大的数)
- 用快速排序的思想求第K大的数或最大的k个数
- 面试坑
- 对兼容性的认识
- 图片加载框架Fresco的使用
- CrackMe ——记一次逆向练手
- C++笔试题(八).B站
- 利用快速排序找到第k大的数字
- javaSE 方法
- [codevs1213]解的个数(数论,扩欧)
- 使用ViewPager实现自动轮播
- Big Countries
- php7.1遇到的错误
- SVN库迁移整理方法总结
- matrix fast pow
- synchronized和lock以及synchronized和volatile的区别