线性时间算法解决最大间隙问题

来源:互联网 发布:圣思园java视频 编辑:程序博客网 时间:2024/04/30 14:42

1. 问题描述:

   最大间隙问题:给定n个实数x1,x2,...,xn,求这n个实数 在实轴上 相邻2个数之间 最大差值

2. 实现要求:

   (1)算法复杂度为线性时间;

   (2)输入数据由input.txt的文件提供,文件第一行有1个正整数n,接下来的一行有n个实数x1,x2,x3...

   (3)程序结束时,将找到的最大间隙输出到文件output.txt中。

3. 解决思想:

(1)找到n个数据中最大和最小数据maxx和minx;

(2)用n-2个点等分区间[minx,maxx],即将[minx,maxx]等分为n-1个区间(前闭后开区间),将这些区间看做桶,编号为1,2,...,n-2,n-1,且桶i的上界和桶i+1的下界相同,即每个桶的大小相同,每个大小为: dblAvrGap=(maxx-minx)/(n-1);

(3)将n个数放入n-1个桶中:按如下规则将x[i]分配到某个桶(编号index)中:  index=int((x[i]-minx)/dblAvrGap)+1;

(4)求最大间隙:除最大最小数据maxx和minx以外的n-2个数据被放入n-1个桶中,因此至少有一个桶是空的,又因肯定有空桶存在,所以最大间隙            不会在同一桶中出现,而是在空桶两侧!又因求的是实数轴相邻两数的差值,因此和空桶两侧桶中间的数无关,即最大间隙在桶i的上界和桶j的下界之间产生(j>=i+1)。

4. 源代码:

/************************************************************************* 最大间隙问题:给定n个实数x1,x2,...,xn,求这n个实数在实轴上相邻2个数之间*   的最大差值,要求设计线性的时间算法************************************************************************/#include<iostream>#include<fstream>//#include<iomanip>using namespace std;#define FILENAMELENGTH 50//声明函数template<class T>int indexofmin(int n, T *x);template<class T>int indexofmax(int n, T *x);//类class CMaxGap{public:int m_nCount;        //数据的个数double m_dblMaxGap;    //最大间隙double *m_dblNumber;//存放数据的数组CMaxGap(const char *filename);~CMaxGap();double GetMaxGap(int n, double *x);void Display();};//读入数据CMaxGap::CMaxGap(const char *filename)//指定目录用单斜杠{FILE *fp = fopen(filename, "r");if (fp == NULL){printf("can not open file!");exit(0);}//读入数据个数fscanf(fp, "%d", &m_nCount);//fscanf遇到空格和换行时结束m_dblNumber = new double[m_nCount];//读入每个具体的数据for (int i = 0; i<m_nCount; i++)fscanf(fp, "%lf", &m_dblNumber[i]);m_dblMaxGap = 0;fclose(fp);}CMaxGap::~CMaxGap(){delete[] m_dblNumber;m_dblNumber = NULL;}//获取n个数据的最大间隙,存放在以x为开始地址的单元中,数据下标为0,1,...,n-1double CMaxGap::GetMaxGap(int n, double *x){//找到最大最小数据,考虑到浮点型数据在传递过程中可能会有微小的变化//故采取取其下标的方式,在直接读取int minindex = indexofmin(n, x);int maxindex = indexofmax(n, x);double minx = x[minindex];double maxx = x[maxindex];//用n-2个点等分区间[minx,maxx],产生n-1个桶,桶编号1,2,...,n-2,n-1//且桶i的上界和桶i+1的下届相同double dblAvrGap = (maxx - minx) / (n - 1);    //每个等分区间大小,即每个桶的大小int *count = new int[n];        //实际分到每个桶的数据个数double *low = new double[n];    //实际分到每个桶的最小数据double *high = new double[n];    //实际分到每个桶的最大数据 //初始化桶for (int i = 0; i<n; i++){count[i] = 0;low[i] = maxx;high[i] = minx;}int index;    //桶编号  //将n个数放入n-1个桶中for (int i = 0; i<n; i++){//按如下规则将x[i]分配到某个桶(编号index)中//若x[i]=minx,则被分到第1个桶中(minx即为桶1的下界)//若x[i]=桶j的下界(也是桶j-1的上界),则按如下公式被分到桶j中(j>=1)index = int((x[i] - minx) / dblAvrGap) + 1;//若x[i]=maxx,则被分到桶n中(max为桶n的下界桶n-1的上界)//    但没有桶n,此时可人为将其移入桶n-1中,或者再加一个桶//该步操作不影响下面的求最大间隙if (index == n)index--;count[index]++;// 统计实际分到每个桶的数据个数//调整分到该桶的最大最小数据if (x[i]<low[index])low[index] = x[i];if (x[i]>high[index])high[index] = x[i];//只需确定每个桶的上界下界即可,中间的数无用}//除最大最小数据maxx和minx以外的n-2个数据被放入n-1个桶中,因此至少有一个桶是空的//又因肯定有空桶存在,所以最大间隙不会在同一桶中出现,而是在空桶两侧//因求得是实数轴相邻两数的差值,因此和空桶两侧桶中间的数无关//  即最大间隙在桶i的上界和桶j的下界之间产生(j>=i+1)//计算最大间隙double dblMaxGap = 0, dblHigh = high[1], dblTempGap;for (int i = 2; i<n; i++){if (count[i])    //该桶非空才计算{dblTempGap = low[i] - dblHigh;if (dblMaxGap<dblTempGap)dblMaxGap = dblTempGap;dblHigh = high[i];}}//释放delete[] count;count = NULL;delete[] low;low = NULL;delete[] high;high = NULL;m_dblMaxGap = dblMaxGap;return dblMaxGap;}void CMaxGap::Display(){printf("%d numbers:   ", m_nCount);for (int i = 0; i<m_nCount; i++){printf("%.2f ", m_dblNumber[i]);}printf("\nthe max gap is: %.2f \n", m_dblMaxGap);//同时将结果保存至TXT文件ofstream f1("output.txt"); //注意若输出到指定目录要用双斜杠 d:\\XMP\\output.txtif (!f1)return;f1 << m_dblMaxGap << endl;f1.close();}//求数组中最小数据的下标template<class T>int indexofmin(int n, T *x){int index;T temp = x[0];for (int i = 1; i<n; i++){if (x[i]<temp){temp = x[i];index = i;}}return index;}//求数组中最大数据的下标template<class T>int indexofmax(int n, T *x){int index;T temp = x[0];for (int i = 1; i<n; i++){if (x[i]>temp){temp = x[i];index = i;}}return index;}//显示菜单void show_menu(){printf("--------------------------------------------- \n");printf("input command to test the program \n");printf("   i or I : input filename to test \n");printf("   q or Q : quit \n");printf("--------------------------------------------- \n");printf("$ input command >");}void main(){char sinput[10];char sfilename[FILENAMELENGTH];show_menu();scanf("%s", sinput);while (_stricmp(sinput, "q") != 0)//比较字符串,且不区分大小写{if (_stricmp(sinput, "i") == 0){printf("\nplease input a filename:");scanf("%s", sfilename);//求文件中数据的最大间隙CMaxGap gap(sfilename);double dblMaxGap = gap.GetMaxGap(gap.m_nCount, gap.m_dblNumber);gap.Display();}//输入命令printf("$ input command >");scanf("%s", sinput);}}





 

1 0
原创粉丝点击