利用分治法求一组数据中最大的两个数和最小的两个数。

解题思路:二分法,保留每个子问题的最小的两个数和最大的两个数

方案一:

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

#include<iostream>

float a[100];

float  max1, max2, min1, min2;  //min1<min2,  min1保存最小的数, min2 保存次小数; max2<max1,  max1保存最大数, max2保存次大数   

void min_maxtwo (int i, int j, float &fmin2, float &fmin1, float &fmax2, float &fmax1) //fmin1存放最小的数,fmin2存放次小的数 
{
    float lmin2, lmin1, rmin2, rmin1, lmax2, lmax1, rmax2, rmax1;
    int mid;
   
    if (i==j)
    {
       fmin2=fmin1=a[i]; 
       fmax2=fmax1=a[i];   
    }
    else if (i==j-1)
            if (a[i]<a[j])
               { fmax1=fmin2=a[j]; fmax2=fmin1=a[i];}
            else
               { fmax1=fmin2=a[i]; fmax2=fmin1=a[j]; }
    else 
    {
        mid=(i+j)/2;
        min_maxtwo (i, mid, lmin2, lmin1, lmax2, lmax1);     
        min_maxtwo (mid+1, j, rmin2, rmin1, rmax2, rmax1);
      //以下求最小的两个数

       if (lmin1<rmin1)  
           if(lmin2<rmin1)
           { fmin1=lmin1; fmin2=lmin2; }
           else
           { fmin1=lmin1; fmin2=rmin1;}
        else
        {
            if (rmin2<lmin1)
            { fmin1=rmin1; fmin2=rmin2; }
            else
            { fmin1=rmin1; fmin2=lmin1;}   
        } 
        //**********%%%%%%&&&&&&&&&&&  

     //以下求最大的两个数
        if (lmax1<rmax1)
           if(lmax1<rmax2)
           { fmax1=rmax1; fmax2=rmax2; }
           else
           { fmax1=rmax1; fmax2=lmax1;}
        else  //lmax1>rmax1
        {
            if (lmax2<rmax1)
            { fmax1=lmax1; fmax2=rmax1; }
            else
            { fmax1=lmax1; fmax2=lmax2;}   
        }   
    } 
}


//float second (int n)
//{
// //float  min2, min1;
// two(0, n-1, min2, min1);
// printf("min1=%.2f, min2=%.2f", min1, min2);
//}
 
void second (int n)
{
 //float  min2, min1;
 min_maxtwo(0, n-1, min2, min1, max2, max1);
 //printf("min1=%.2f, min2=%.2f", min1, min2);
}


int main( )
{
  int i, n=8;          
 // float  max1, max2, min1, min2;
  printf("请输入一组数:\n");
  for (i=0;i<n;i++)   
     scanf("%f", &a[i]);
  
  second(n);
  printf("%f, %f, %f, %f\n", min1, min2, max2, max1);
 
 system ("pause");
 return 0;   

}

运行结果:

请输入一组数:
1 2 -3 4 6 10 20 -11
-11.000000, -3.000000, 10.000000, 20.000000
请按任意键继续. . .

 

方案二:

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

float a[100];
float  max1, max2, min1, min2;  //min1<min2,  min1保存最小的数, min2 保存次小数; max2<max1,  max1保存最大数, max2保存次大数   

void mintwo (int i, int j, float &fmin2, float &fmin1) //fmin1存放最小的数,fmin2存放次小的数 
{
    float lmin2, lmin1, rmin2, rmin1;
    int mid;
   
    if (i==j)
    { fmin2=fmin1=a[i]; }
    else if (i==j-1)
            if (a[i]<a[j])
               { fmin2=a[j]; fmin1=a[i];}
            else
               { fmin2=a[i]; fmin1=a[j]; }
    else
    {
        mid=(i+j)/2;
        mintwo (i, mid, lmin2, lmin1);     
        mintwo (mid+1, j, rmin2, rmin1);
        if (lmin1<rmin1)
           if(lmin2<rmin1)
           { fmin1=lmin1; fmin2=lmin2; }
           else
           { fmin1=lmin1; fmin2=rmin1;}
        else
        {
            if (rmin2<lmin1)
            { fmin1=rmin1; fmin2=rmin2; }
            else
            { fmin1=rmin1; fmin2=lmin1;}   
        } 
    } 
}


void maxtwo (int i, int j, float &fmax2, float &fmax1) //fmax1存放最大的数,fmax2存放次大的数 
{
    float lmax2, lmax1, rmax2, rmax1;
    int mid;
   
    if (i==j)     { fmax2=fmax1=a[i]; }
    else if (i==j-1)
            if (a[i]<a[j])
               { fmax1=a[j]; fmax2=a[i];}
            else
               { fmax1=a[i]; fmax2=a[j]; }
    else
    {
        mid=(i+j)/2;
        maxtwo (i, mid, lmax2, lmax1);     
        maxtwo (mid+1, j, rmax2, rmax1);
        if (lmax1<rmax1)
           if(lmax1<rmax2)
           { fmax1=rmax1; fmax2=rmax2; }
           else
           { fmax1=rmax1; fmax2=lmax1;}
        else  //lmax1>rmax1
        {
            if (lmax2<rmax1)
            { fmax1=lmax1; fmax2=rmax1; }
            else
            { fmax1=lmax1; fmax2=lmax2;}   
        }   
    } 
}


void second (int n)
{ mintwo(0, n-1, min2, min1); 
  maxtwo(0, n-1, max2, max1);
}


int main( )
{
  int i, n=8;          
  printf("请输入一组数:\n");
  for (i=0;i<n;i++)   
     scanf("%f", &a[i]);
  
  second(n);
  printf("%f, %f, %f, %f\n", min1, min2, max2, max1);
 
 system ("pause");
 return 0;   

}
 

 

  • 2
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构与算法 排序算法 内排序 八大基础排序 选择排序 简单选择排序 思想 每次选择最大的数插入到末尾 做法 外层for循环控制次数 内层for循环找出最大的值的角标 找出最大角标后,进行交换 优化思路 同时获取最大值和最小值,然后分别插入数组的首部和尾部 堆排序 思想 使用大顶堆的思想来排序,每次建堆后交换 做法 总体:建堆-替换 建堆 只要左子树或右子树大于当前根节点,则替换 替换后会导致下面的子树发生了变化,因此同样需要进行比较,直至各个节点实现父>子这么一个条件(递归) 交换排序 冒泡排序 思想 每次俩俩交换,将最大值交换到末尾 做法 外层for控制循环次数 内层for控制比较次数 每次循环之后,比较次数都会减少一次 优化思路 如果一趟排序后没有发生位置变化,那么此时就是有序了 快速排序 思想 每次将比支点小的放在支点左边,比支点大的放在支点右边 做法 外循环while只要i和j不碰撞查找 内层个while循环分别查找出比支点小的和比支点大的角标 如果i<=j满足条件,就交换 一趟排序后,支点的左边都比支点小,支点右边都比支点大 只要满足L<j,i0的条件查找出要插入的何时位置 退出内层while循环后就找到了合适的位置插入 优化思路 二分查找插入,找合适位置的时候使用二分查找算法 希尔排序 思想 用增量来将数组进行分隔,直到增量为1。底层干的还是插入排序干的活 做法 最外层for外循环控制增量的数量,每次/2 第二层for循环控制每次增量那组开始进行插入排序,直至完毕 第三层while循环找到要插入到哪个位置 归并排序 思想 将个已排好序的数组合并成一个有序的数组 做法 递归拆分出个有序的数组,从mid的位置开始拆分,递归出口:只有一个值的时候就不用拆分了 合并个有序的数据 分别往个数组填充已有序的数据 比较个数组的值谁小,谁小就放到我们的数组 如果比较完之后还有剩余的数据,那么用while直接添加到我们的总数组 优化思路 当递归到规模足够小时,利用插入排序 归并前判断一下是否还有必要归并 只在排序前开辟一次空间 基数(桶)排序 思想 分配,回收(分配到不同的位置上,然后回收)..不断分配..回收来进行排序,直到有序 做法 分配一个[array.length][10列]的二维数组来装我们的元素 最外层for循环控制要分配和回收的次数(根据最大值) 将元素的个、十、百位依次放到桶子上(第一次就是放个位,第二次放十位) 依据每列回收桶子,个for循环 外排序 查找算法 二分查找 分块查找 哈希查找 贪心算法 最小生成树的Prim算法和Kruskal算法 爬山问题 回溯算法 n皇后问题 动态规划Dynamic Planning 应用 最长公共子序列LCS 矩阵连乘问题 爬楼梯问题 找零问题 0-1背包问题 分治算法Divide and Conquer 应用:归并排序 其它 Rabin fingerprints 文件指纹算法 BitMap 位图算法 BloomFilter 布隆过
一、本书的内容 目前,市面上有关计算机算法的书很多,有些叙述严谨但不全面,另外一些则是容量很大但不够严谨。本书将叙述的严谨性以及内容的深度和广度有机地结合了起来。第1版推出后,即在世界范围内受到了广泛的欢迎,被各高等院校用作多种课程的教材和业界的标准参考资料。它深入浅出地介绍了大量的算法及相关的数据结构,以及用于解决一些复杂计算问题的高级策略(如动态规划、贪心算法、平摊分析等),重点在于算法的分析和设计。对于每一个专题,作者都试图提供目前最新的研究成果及样例解答,并通过清晰的图示来说明算法的执行过程。. 本书是原书的第2版,在第1版的基础之上增加了一些新的内容,涉及算法的作用、概率分析和随机化算法、线性规划,以及对第1版详尽的、几乎涉及到每一小节的修订。这些修订看似细微,实际上非常重要。书引入了“循环不变式”,并贯穿始终地用来证明算法的正确性。在不改动数学和分析重点的前提下,作者将第1版的许多数学基础知识从第一部分移到了附录。 二、本书的特点 本书在进行算法分析的过程,保持了很好的数学严谨性。书的分析和设计可以被具有各种水平的读者所理解。相对来说,每一章都可以作为一个相对独立的单元来教授或学习。书的算法以英语加伪代码的形式给出,只要有一点程序设计经验的人都能读懂,并可以用任何计算机语言(如C/C++和Java等)方便地实现。在书,作者将算法的讨论集在一些比较现代的例子上,它们来自分子生物学(如人类基因项目)、商业和工程等领域。每一小节通常以对相关历史素材的讨论结束,讨论了在每一算法领域的原创研究。 本书的特点可以概括为以下几个方面: 1.概念清晰,广度、深度兼顾。 本书收集了现代计算机常用的数据结构和算法,并作了系统而深入的介绍。对涉及的概念和背景知识都作了清晰的阐述,有关的定理给出了完整的证明。 2.“五个一”的描述方法。 本书以相当的深度介绍了许多常用的数据结构和有效的算法。编写上采用了“五个一”,即一章介绍一个算法、一种设计技术、一个应用领域和一个相关话题。.. 3.图文并茂,可读性强。 书的算法均以通俗易懂的语言进行说明,并采用了大量插图来说明算法是如何工作的,易于理解。 4.算法的“伪代码”形式简明实用。 书的算法均以非常简明的“伪代码”形式来设计,可以很容易地把它转化为计算机程序,直接应用。 注重算法设计的效率,对所有的算法进行了仔细、精确的运行时间分析,有利于进一步改进算法。 三、本书的用法 本书对内容进行了精心的设计和安排,尽可能考虑到所有水平的读者。即使是初学计算机算法的人,也可以在本书找到所需的材料。 每一章都是独立的,读者只需将注意力集到最感兴趣的章节阅读。 1.适合作为教材或教学参考书。 本书兼顾通用性与系统性,覆盖了许多方面的内容。本书不但阐述通俗、严谨,而且提供了大量练习和思考题。针对每一节的内容,都给出了数量和难度不等的练习题。练习题用于考察对基本内容的掌握程度,思考题有一定的难度,需进行精心的研究,有时还通过思考题介绍一些新的知识。 前言回到顶部↑本书提供了对当代计算机算法研究的一个全面、综合性的介绍。书给出了多个算法,并对它们进行了较为深入的分析,使得这些算法的设计和分析易于被各个层次的读者所理解。力在不牺牲分析的深度和数学严密性的前提下,给出深入浅出的说明。. 书每一章都给出了一个算法、一种算法设计技术、一个应用领域或一个相关的主题。算法是用英语和一种“伪代码”来描述的,任何有一点程序设计经验的人都能看得懂。书给出了230多幅图,说明各个算法的工作过程。我们强调将算法的效率作为一种设计标准,对书的所有算法,都给出了关于其运行时间的详细分析。 本书主要供本科生和研究生的算法或数据结构课程使用。因为书讨论了算法设计的工程问题及其数学性质,因此,本书也可以供专业技术人员自学之用。 本书是第2版。在这个版本里,我们对全书进行了更新。所做的改动从新增了若干章,到个别语句的改写。 致使用本书的教师 本书的设计目标是全面、适用于多种用途。它可用于若干课程,从本科生的数据结构课程到研究生的算法课程。由于书给出的内容比较多,只讲一学期一般讲不完,因此,教师们应该将本书看成是一种“缓存区”或“瑞典式自助餐”,从挑选出能最好地支持自己希望教授的课程的内容。 教师们会发现,要围绕自己所需的各个章节来组织课程是比较容易的。书的各章都是相对独立的,因此,你不必担心意想不到的或不必要的各章之间的依赖关系。每一章都是以节为单位,内容由易到难。如果将本书用于本科生的课程,可以选用每一章的前面几节内容;在研究生课程,则可以完整地讲授每一章。 全书包含920多个练习题和140多个思考题。每一节结束时给出练习题,每一章结束时给出一些
### 回答1: 利用分治法个数最大个数最小个数。 解释:该题要在一个数找出最大个数最小个数,可以利用分治法分别最大个数最小个数。具体步骤是将数据分成部分,继续递归地分别出左右部分的最大个数最小个数,然后将结果合并得到全局的最大个数最小个数。 ### 回答2: 分治法是一种重要的算法思想,其思想是将问题分解成若干个子问题,然后将子问题逐个解并合并成原问题的解。在一组数据最大个数最小个数的问题,可以采用分治法,具体步骤如下: 1. 将原问题分解成个子问题,分别出子问题最大最小数。 2. 对于个子问题的最大数,取其最大的一个。 3. 对于个子问题的最小数,取其最小的一个。 4. 比较第2步和第3步得到的结果,即可得到原问题的最大个数最小个数。 具体实现时,我们可以采用递归的方法对数据进行分治。在每一次递归时,把数据分成半,然后分别出左半部分和右半部分的最大最小数,并进行比较。 时间复杂度分析:假设有n个数,由于每次递归要处理一半的数据,因此递归树的高度为logn。对于每个子问题,在最大最小数时需要比较三次,因此子问题的时间复杂度为O(3)。因此,整个算法的时间复杂度可以表示为O(3*logn)=O(logn)。所以,采用分治法一组数据最大个数最小个数的时间复杂度为O(logn)。 总之,分治法是一种高效且常用的算法思想,利用分治法一组数据最大个数最小个数的问题,可以大大提高算法的效率。 ### 回答3: 分治法是一种高效的算法,可用于解决各种问题,包括查找一组数据最大个数最小个数分治法的基本思路是将一个大问题分成若干个相对简单的子问题,分别解这些子问题,最后将结果合并得到最终解。 利用分治法一组数据最大个数最小个数的步骤如下: 1. 将原始数据分成个子问题。 2. 对每个子问题进行递归解,直到问题变得足够简单。 3. 合并个子问题的结果。 4. 返回最大个数最小个数的值。 具体实现时,可以将数据分成个子问题,然后对每个子问题再次使用分治法,直到每个子问题只包含一个数。然后可以比较这个子问题的最大数和最小数,得到全局的最大数和最小数。最后,将全局的最大数和次大数以及最小数和次小数比较,得到最大个数最小个数。 以下是具体实现的伪代码: ``` function find_max_min_numbers(array): if size(array) == 1: return (array[0], array[0]) else if size(array) == 2: return (max(array[0], array[1]), min(array[0], array[1])) mid = size(array) / 2 left_max, left_min = find_max_min_numbers(array[0:mid]) right_max, right_min = find_max_min_numbers(array[mid:size(array)]) max1, max2 = max(left_max, right_max), min(left_max, right_max) min1, min2 = min(left_min, right_min), max(left_min, right_min) return (max1, max2, min1, min2) ``` 该算法的时间复杂度为 O(nlogn),因为需要递归解问题,在每个递归层级上需要进行 O(n) 次比较。但是,与其他 O(nlogn) 的算法相比,该算法具有更好的空间利用率,因为它使用了分治法的思想,即在任何时候,只需要存储当前问题的一部分,而不是整个数据集合。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值