实训三—分治算法专题—第7关:输出前m大的数


任务描述

本关任务:给定一个数组包含n个元素,统计前m大的数并且把这m个数输出。

相关知识

思路:用分治处理,把前m大的都交换到数组最右边,再输出。

可以调用函数Partition( ),在O(n)时间内把数组前m大的都交换到最右边。

  1. 设key=a[0], 调用Partition()函数将数组划分为两个子表,使得比key小的元素都在key左边,比key大的元素都在key右边(线性时间完成)
  2. 分以下三种情况选择数组的前子表或后子表再调用Partition函数 a = m 完成 a > m 对右边子表再进行Partition( ) a < m 对左边子表再进行Partition( )

数组划分示意图

编程要求

根据提示,在右侧编辑器补充代码,输出前m大的数。

测试说明

平台会对你编写的代码进行测试:

测试输入: 20 6 预期输出: Before sort: 11,58,97,59,96,81,62,41,40,81,50,24,47,9,44,9,65,7,79,59, After sort: 7,9,9,11,58,44,47,41,40,24,50,59,62,59,65,79,81,81,96,97,

测试输入: 30 8 预期输出: Before sort: 33,71,30,21,52,54,34,72,82,99,98,39,70,54,66,85,13,7,69,47,39,57,97,29,49,59,75,29,93,44, After sort: 29,29,30,21,7,13,33,44,71,59,49,39,70,54,66,52,34,54,69,47,39,57,72,97,85,98,75,99,93,82,

#include <stdio.h>
#include<stdlib.h>  


int Partition(int *L,int low,int high) ; //交换顺序表L中子表L[low..high]的记录,使枢轴记录到位,并返回其所在位置,此时在它之前(后)的记录均不大(小)于它。 
void QSortM(int *L,int low,int high,int m) ; 
void output(int *a,int n) ;
void swap(int &a, int &b) ;		

int main()  
{  
    int *a=0;  
    int left=0,right=10; //初始化left和right的值  
	int k,m,n,i; 	  
    scanf("%d",&n);  
    srand(n);  
    a=new int[n];      
    for(i=0;i<n;i++)
    {        
        a[i]=rand() % 100;
    }             
    
    printf("Before sort:\n");  
    output(a,n); 
    scanf("%d",&m); 
    left=0,right=n-1; //初始化left和right的值  
    QSortM(a,left,right,m);    
    printf("After sort:\n");  
    output(a,n); 
    printf("\n"); 
	system("pause"); 
    return 0;
} 

void swap(int &a, int &b)  
{  
    int t;  
    t=a;a=b;b=t;  
}


void output(int *a,int n)  
{  
    int i;  
    for(i=0;i<n;i++)  
    {  
        printf("%d,",a[i]);  
    }  
    printf("\n");  
}

//交换顺序表L中子表L[low..high]的记录,使枢轴记录到位,并返回其所在位置,此时在它之前(后)的记录均不大(小)于它。  
int Partition(int *L,int low,int high)  
 {  
   int t;  
   int pivotkey;  
   pivotkey=L[low]; // 用子表的第一个记录作枢轴记录  
   while(low < high)  
   { // 从表的两端交替地向中间扫描  
     while( low<high && L[high]>=pivotkey)  
       --high;  
     swap(L[low], L[high]); // 将比枢轴记录小的记录交换到低端      
     while(low<high && L[low]<=pivotkey)  
       ++low;  
     swap(L[low],L[high]);        ; // 将比枢轴记录大的记录交换到高端  
   }  
    return low; // 返回枢轴所在位置  
 }

 void QSortM(int *L,int low,int high,int m)  
 {   
   /********** Begin **********/
      if(low < high){
        int pivot = Partition(L, low, high); // 将数组划分为两个子表
        if(high - pivot + 1 == m) // 找到了前m大的数
          return;
        else if(high - pivot + 1 > m) // 前m大的数在右边子表
          QSortM(L, pivot+1, high, m);
        else // 前m大的数在左边子表
          QSortM(L, low, pivot-1, m-(high-pivot+1));
      }
   /********** End **********/
 }        

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值