题目描述:
给定一个数组包含n个元素,统计前m大的数并且把这m个数从大到小输出
代码:
#include<iostream>
using namespace std;
typedef int ElementType;
//分治处理 O(n+mlog(m))
//用O(n)把m大个数挪到右边,然后对这m个数快速排序再输出
//快速排列法
void Qsort(ElementType a[], int left,int right)
{
if (left >= right)
return;
int low=left, high=right;
int pivot = a[left];
while (low<high)
{
while (a[high] >= pivot && low < high){ high--; }
swap(a[low], a[high]);
while (a[low] <= pivot && low < high){ low++; }
swap(a[low], a[high]);
}
Qsort(a, left, low - 1);
Qsort(a, low + 1, right);
}
//把数组前k大的都弄到最右边
void arrangeRight(ElementType a[], int left, int right, int k)
{
if (left >= right)
return;
if (k == right - left + 1) //要弄的数组元素的个数不能等于 k(因为 0 也算一个位置,所以要 +1 )
return;
int low = left, high = right;
int pivot = a[low];
while (low < high) //停止循环后 low 和 high 处于同一位置
{
while (a[high] >= pivot && low < high){ high--; }
swap(a[left], a[right]);
while (a[low] <= pivot && low < high){ low++; }
swap(a[low], a[high]);
}
if (right - low + 1 == k) //右边的数刚好为e-i+1为k个
return;
else if (right - low + 1 > k)
arrangeRight(a, low + 1, right, k); //右边的数大于k个
else
arrangeRight(a, left, low-1, k-right+low-1);//右边的数小于k个,需要左边取出k - (right-low+1)个
}
void printM(ElementType a[],int n,int m)
{
if (n < m)
return;
arrangeRight(a, 0, n - 1, m); //O(N)时间内先把m大的都弄到数组最右边
Qsort(a, n - m, n - 1); //对这m个数排序
for (int i = 0; i < m; i++, n--)
cout << a[n - 1] << " ";
cout << endl;
}
int main()
{
int a[] = { 11, 4, 14, 6, 1, 12, 8, 9, 3, 13, 7, 10, 0, 5, 2, 15 };
int len = sizeof(a) / sizeof(a[0]);
printM(a, len, 8);
return 0;
}
我学到的:
C++使用swap()函数不用加头文件,因为其包含于std::标准名词空间中
解释一下本代码所用的快速排序法:
这种快速排序法与一般的没什么太大区别,一般的可以参考另一篇博客:快速排列法(简易版 → 复杂版),但主要的区别体现在代码的16至19行,它是while一次,swap一次,而一般的是先while两次,swap一次,相比较的话,本代码所用的比较慢,因为交换后可能存在还是不满足条件的情况,但这只能等下一次循环了,所以循环的此数会增加,所以还是先while两次,swap一次效率高 (所以本代码只是为了举例)
复杂度分析:
将前m大的都弄到数组最右边的时间:
T(n) = T(n/2) + a * n //T(n/2)是当右边的数不等于k时继续分的情况, a * n 是遍历完的情况
= T(n/4) + a * n/2 + a * n
= T(n/8) + a * n/4 + a * n/2 + a * n
= ……
= T(1) + … + a * n/8 + a * n/4 + a * n/2 + a * n
< 2 * a * n //最坏也不可能超过 2 * a * n
即O(n);
而将前m大的元素排序,复杂度为O(mlog(m))
故整体的时间复杂度为:复杂度O(n+mlog(m))