归并排序和快速排序的衍生问题(二)
来源:互联网 发布:java final 变量 回收 编辑:程序博客网 时间:2024/05/14 05:49
取数组中第n大的元素
取数组中第n大的元素这个问题,相信大家在学习数据结构这门课中都遇到过。通常我们会使用某一排序算法先将数组排序,然后在来找数组中第n大的元素。此时,数组中第n大的元素其在数组中的位置也为第n个。
利用这一思想,我们可以使用快速排序算法来将该求解算法的时间复杂度变为O(n)。为什么呢?在快速排序算法中,每一趟快速排序都会确定一个元素(基准)的位置,例如:假设现在基准为5,经过一趟快速排序后,我们知道在第五个元素(即该元素为5)之前的元素都小于5,在第五个元素之后的元素都大于5,这时我们不就确定了元素(基准)为5在数组中的位置吗?
我们先使用第一种方法来求解数组中第n大的元素,即先排序再找第n大的元素,其基本代码如下:
// 3-路快速排序算法void __quickSort(int arr[], int l, int r) { if (l >= r) return; swap(arr[l], arr[rand() % (r - l + 1) + l]); int v = arr[l]; // arr[l+1...lt] < v int lt = l; // arr[gt...r] > v int gt = r + 1; // arr[lt+1...i) == v int i = l + 1; while (i < gt) { if (arr[i] < v) { swap(arr[i], arr[lt + 1]); lt++; i++; } else if (arr[i] > v) { swap(arr[i], arr[gt - 1]); gt--; } else { i++; } } swap(arr[l], arr[lt]); __quickSort(arr, l, lt - 1); __quickSort(arr, gt, r);}int __selection(int arr[], int n, int k) { srand(time(NULL)); __quickSort(arr, 0, n - 1); return arr[k];}// 寻找arr数组中第k大的元素int selection(int arr[], int n, int k) { // 如果k >= 0 && k < n不成立,则终止程序执行 assert(k >= 0 && k < n); return __selection(arr, n, k);}
现在,我们来修改一下代码,使其成为第二种方法,其代码如下:
int __partition(int arr[], int l, int r) { swap(arr[l], arr[rand() % (r - l + 1) + l]); int v = arr[l]; // arr[l+1...lt] < v int lt = l; // arr[gt...r] > v int gt = r + 1; // arr[lt+1...i) == v int i = l + 1; while (i < gt) { if (arr[i] < v) { swap(arr[i], arr[lt + 1]); lt++; i++; } else if (arr[i] > v) { swap(arr[i], arr[gt - 1]); gt--; } else { i++; } } swap(arr[l], arr[lt]); return lt;}int __selection(int arr[], int l, int r, int k) { if (l == r) return arr[l]; int p = __partition(arr, l, r); if (k == p) return arr[p]; else if (k < p) return __selection(arr, l, p - 1, k); else return __selection(arr, p + 1, r, k);}// 寻找arr数组中第k大的元素int selection(int arr[], int n, int k) { // 如果k >= 0 && k < n不成立,则终止程序执行 assert(k >= 0 && k < n); srand(time(NULL)); return __selection(arr, 0, n - 1, k);}
这样,我们就解决了求取数组中第n个大元素的问题。
注:在main()中的代码如下:
int main() { // 生成一个大小为n, 包含0...n-1这n个元素的随机数组arr int n = 10000; int *arr = TestHelper::generateOrderedArray(n); TestHelper::shuffleArray(arr, n); // 验证selection算法, 对arr数组求第i小元素, 应该为i for (int i = 0; i < n; i++) { assert(selection(arr, n, i) == i); cout << "test " << i << " complete." << endl; } cout << "Test selection completed." << endl; delete[] arr; return 0;}
由于测试方法为遍历输出,故不贴出程序运行结果。
阅读全文
0 0
- 归并排序和快速排序的衍生问题(二)
- 归并排序和快速排序的衍生问题(一)
- 3-9 归并排序和快速排序的衍生问题
- 归并排序和快速排序的衍生问题(逆序对)
- 归并排序与快速排序的衍生问题
- 排序算法二(归并排序、快速排序、希尔排序)
- 归并排序和快速排序的比较
- 归并排序和快速排序的浅析
- 单链表的快速排序和归并排序
- 归并排序和快速排序的实现
- 归并排序和快速排序的比较
- 快速排序和归并排序的实现
- 简单排序Java实现(二):归并排序,快速排序
- 快速排序和归并排序
- 归并排序和快速排序
- 归并排序和快速排序
- 归并排序和快速排序
- 归并排序和快速排序
- hadoop 经典入门wordcount
- 198. House Robber(入室强盗)
- ros学习笔记3
- Python中的map()函数和reduce()函数的用法
- maven 下载及配置
- 归并排序和快速排序的衍生问题(二)
- 框架制作淘宝注册表--不掺杂任何CSS
- 【shell实例】一键自动化pull->更新文件->commit->压缩打包->上传服务器
- [bzoj4976]宝石镶嵌
- BZOJ 1477 青蛙的约会 [扩展欧几里得]
- Package com.google.gson 的 API 的学习(1)
- NOIP提高组——线段树
- vim简单用法
- Linux下普通用户执行关机、重启指令