c语言寻找第k小的数,快排算法及利用快排思想寻找第k大(小)的数

#include

#include

using namespace std;

void Swap(int &a, int &b)

{

int p = a;

a = b;

b = p;

}

void print(int* arry, int num)

{

int i;

for(i = 0; i < num; i++)

cout << arry[i] << " ";

cout << endl;

}

//递归实现快速排序

void my_qsort(int *arry, int left, int right)

{

if(!arry || left < 0 || right < 0)

return;

int i, j;

if(left < right)

{

i = left;

j = right;

int x = arry[i];

while(i < j)

{

while((i < j) && (arry[j] > x)) --j; //从右向左寻找比x小的数

while((i < j) && (arry[i] < x)) ++i; //从左向由寻找比x大的数

Swap(arry[i], arry[j]);

}

arry[i] = x;

my_qsort(arry, left, i - 1);

my_qsort(arry, i + 1, right);

}

}

int partition(int *arry, int left, int right)

{

int x = arry[left];

int i, j;

i = left;

j = right;

while(i < j)

{

while((i < j) && (arry[j] > x)) --j;

while((i < j) && (arry[i] < x)) ++i;

Swap(arry[i], arry[j]);

}

arry[i] = x;

return i;

}

//非递归实现快速排序

void my_qsort2(int *arry, int left, int right)

{

if(!arry || left < 0 || right < 0)

return;

stack stk;

if(left < right)

{

int mid = partition(arry, left, right);

if(left < mid - 1){

stk.push(left);

stk.push(mid - 1);

}

if(right > mid + 1){

stk.push(mid + 1);

stk.push(right);

}

while(!stk.empty())

{

int h = stk.top();

stk.pop();

int l = stk.top();

stk.pop();

mid = partition(arry, l, h);

if(l < mid - 1){

stk.push(l);

stk.push(mid - 1);

}

if(h > mid + 1){

stk.push(mid + 1);

stk.push(h);

}

}

}

}

//非递归实现查找无序数组中第k大的数

/* 利用快速排序的思想实现查找第k大的数:快速排序每次选择一个数作为关键数,一次排序这个关键数

的左边都是比它小的数,右边都是比它大的数,所以只要比较下这个关键数所在的下标,就可以知道它是

所有数字中的第几大的数了 */

int find_k_max(int *arry, int num, int k)

{

if(!arry || num <= 0 || k <= 0 || k > num)

return -0xff;

int i, j;

i = 0;

j = num - 1;

int x;

while(1)

{

x = arry[i];

while(i < j)

{

while((i < j) && (arry[j] > x)) --j; //从右向左寻找比x小的数

while((i < j) && (arry[i] < x)) ++i; //从左向由寻找比x大的数

Swap(arry[i], arry[j]);

}

arry[i] = x;

/* 一次快排完毕,这个中间数字是不是要寻找的数 */

if(num - i == k){ //如果是寻找第k小的数,则条件为 i == k

break;

}

else if(num - i < k){ //如果num - i < k则说明我们要寻找的第k大的数在这个中间数字的左边

i = 0;

j = i - 1;

}else{

i++;

j = num - 1;

}

}

return x;

}

//递归实现查找无序数组中第k大的数

int find_k_max2(int *arry, int num, int k)

{

if(!arry || num <= 0 || k <= 0 || k > num)

return -0xff;

int i, j;

i = 0;

j = num - 1;

int x = -0xff;

if(i < j)

{

x = arry[0];

while(i < j)

{

while((i < j) && (arry[j] > x)) --j; //从右向左寻找比x小的数

while((i < j) && (arry[i] < x)) ++i; //从左向由寻找比x大的数

Swap(arry[i], arry[j]);

}

arry[i] = x;

if(num - i == k){

return x;

}

else if(num - i < k){

return find_k_max2(arry, i - 1, k);

}else{

return find_k_max2(arry + i + 1, num - i - 1, k);

}

}

return x;

}

int main()

{

int a[10] = {5, 1, 0, 9, 4, 3, 2, 7, 6, 8};

print(a, 10);

#if 1

cout << "第1大的数为:" << find_k_max2(a, 10, 1) << endl;

print(a, 10);

cout << "第2大的数为:" << find_k_max2(a, 10, 2) << endl;

print(a, 10);

cout << "第3大的数为:" << find_k_max2(a, 10, 3) << endl;

print(a, 10);

#endif

//my_qsort2(a, 0, 9);

my_qsort(a, 0, 9);

print(a, 10);

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值