/**
* -*- coding : utf-8 -*-
* @Author : huangshengjiang
* @Email : 1005542693@qq.com
* @Date : 2016-10-20 10:08
* @Last Modified Date : 2016-10-24 15:51
* @FileName : 最大最小元素.cpp
*/
/*最大最小元素
基本概念 : 用分治的思想快速找出数组A中的最大和最小元素.
(分治思想是将原问题转化为若干相互独立的子问题,
再加子问题结果结合起来,成为原问题的求解)
应用场景 : 1.快速找出数组的数值表示范围/区间.建立有效直观的图表
2.数组是抽象的概念,实际上要看数组所代表的现实意义.
具体需求 : 快速找出数组A的最大最小元素
输入 : 无序数组A[1..n]
输出 : (x,y) 分别是数组A的最大元素和最小元素
分析 : 明确一点,该算法的性能主要是依赖比较次数和交换次数成正比的(O(比较)+O(交换)),两者开销不一样,其中比较开销小,交换开销大.
无论用什么办法要找出数组中的最大最小元素,都需要至少比较依次数组中的每一个元素,
比较次数至少为2n次,关键就在于如何减少交换的次数(占大头).
--等等,如果用指针来进行交换(针对大型结构有效,但是对于当前int数组没有必要,因为指针本身占据4个字节,交换与int的开销一样)
肯定需要至少两个额外空间存放最大最小两个元素.
问题转换为如何将交换次数尽可能减少的同时比较次数进可能接近2n次?
反正都要进行比较,而交换是根据比较的结果决定是否执行的.那么这其中的关键就是如何确定比较的参照值
(首次找出较大范围的较小较大的参照值,这就涉及到比较次数的问题,比较次数接近O(2n),无法避免.可以接受)
问题的关键是快速找出当前数组的较大范围的较小较大参照值?(见方案2)
解决方案1 : 初始以前两个元素作为暂时的最大最小元素,依次遍历数组,每个数值要和当前最大最小值比较,比较次数接近O(1.75n)
交换次数接近O(0.75n)这些都是估摸算的,不是很准确.
优缺点 : 代码易于理解,但是代码执行效率不高,交换次数偏高,舍弃.
解决方案2 : 采用分治递归比较.找出数组的最大最小值.原理: 原数组分为两组,分别计算两组的最小最大元素,进行比较得出最小最大元素.
而两组的最小最大元素则由下一层的划分求得.递归的基础(到哪里返回):当小组个数为1时,返回最大最小值都是该值,
优缺点 : 同级别得到的最小最大元素只要对应比较,能够快速找出较小较大值.减少交换次数.
但是要申请额外的空间进行比较,如果递归次数过多,则有可能产生内存泄漏(不足).当然也是当前最好的.
结论 : 采用分治递归方法.
*/
#include <iostream>
using namespace std;
template <class T>
int Size(T &array)
{
return sizeof(array)/sizeof(array[0]);
}
//函数
void minmax(int * array,int left ,int right,int &min,int &max)//left左边的坐标,最小为0,right右坐标,最大位n-1.
{
int cur = right - left ;
if ( cur == 0 )
{
min = max = array[left];
return ;
}//递归基础
int lmin,lmax;
int rmin,rmax;
minmax(array,left,left + cur/2,lmin,lmax);
minmax(array,left + cur/2 + 1,right,rmin,rmax);
min = lmin <= rmin ? lmin : rmin ;
max = lmax <= rmax ? rmax : lmax ;
}
//测试
int main(int argc, char const *argv[])
{
int a[]={1,3,4,4,6,7,5,3,5,45,675,-1};
int length = Size(a);
cout << length <<endl;
int min,max;
minmax(a,0,length-1,min,max);
cout<< "最小值" << min << ",最大值" << max <<endl;
system("pause");
return 0;
}
转载于:https://www.cnblogs.com/jiangge3/articles/5993328.html