用分治算法解平面最接近点对问题

用分治算法解平面最接近点对问题
用分治算法解平面最接近点对问题

一. 用分治算法解平面最接近点对问题

1.题目

关于最接近点对问题:

给定平面上n个点,找出其中一对点,使得在n个点所构成的所有点对中,该点对的距离最小。

2.程序详细介绍(各模块的功能等)

本程序主要包括两个类:类Point和类Ppoint.其中类Point为处理一些的基本数据传递等.类Ppoint为该程序的主要实现模块,该类中有输入点对的函数shuru,对所输入的点对按X轴排序的函数sort,求各点对的距离的函数xiao等.

假设S中的点为平面上的点,它们都有2个坐标值x和y。为了将平面上点集S线性分割为大小大致相等的2个子集S1和S2,我们选取一垂直线l(方程:x=m)来作为分割直线。其中m为S中各点x坐标的中位数。由此将S分割为S1={p∈S|px≤m}和S2={p∈S|px>m}。从而使S1和S2分别位于直线l的左侧和右侧,且S=S1∪S2 。由于m是S中各点x坐标值的中位数,因此S1和S2中的点数大致相等。递归地在S1和S2上解最接近点对问题,我们分别得到S1和S2中的最小距离δ1和δ2.此即为该程序的大致算法.

3. 程序结构(流程图)

该程序的流程图如下所示

4. 调试与测试:调试方法,测试结果(包括输入数据和输出结果)的分析与讨论

运行该程序时,屏幕上会出现一个界面,首先该界面会提示输入要处理的点对个数,输入点对个数后从键盘输入数字0即可显示出处理后的各个结果,会出现如下结果:

5.程序代码(源程序)

#include

#include

#include

using namespace std;

int i,j,k,d,m,n;

double p2,q,s,r,t;

class Point //创建一个点类//

{

public:

double x;

double y;

double getx()

{

return x;

}

double gety()

{

return y;

}

friend class Ppoint;

};

class Ppoint

{

int sum;

double juli[10][10];

double min[11]; //min[10]用来存放每组中最短的距离//

double mini[11]; //mini[10]用来存放每组中距离最短的点对中的第一个点//

double minj[11]; //minj[10]用来存放每组中距离最短的点对中的第二个点//

Point p[100];

Point p1;

public:

void shuru()

{

cout<<"请输入要处理的点的个数"<

cin>>sum;

for(i=0;i

{

cout<<"请输入点对"<

cin>>p[i].x;

cin>>p[i].y;

cout<

}

}

void sort()

{

cout<<"以下是按x轴上由小到大排序后的点对"<

for(i=0;i

{

for(j=i+1;j

{

if(p[i].x>p[j].x)

{

p1=p[i];

p[i]=p[j];

p[j]=p1;

}

}

}

for(i=0;i

{

cout<

}

}

void xiao()

{

cout<<"以下是对每个模块中的点求距离"<

for(k=0;k

{

cout<<"按任意键继续"<

cin>>i;

cout<<"以下是第"<

for(i=1;i<10;i++)

{

for(j=0;j

{

r=abs(p[k*10+i].x-p[k*10+j].x);

t=abs(p[k*10+i].y-p[k*10+j].y);

juli[i][j]=sqrt(r*r+t*t);

cout<

}

cout<

}

min[k]=juli[k][0],mini[k]=10*k+1,minj[k]=10*k;

for(i=1;i<10;i++)

{

cout<<"\n"<<"第"<

for(j=0;j

{

if(juli[i][j]

{

min[k]=juli[i][j];

mini[k]=10*k+i;

minj[k]=10*k+j;

}

}

}

cout<<"\n"<<"这是第"<

cout<<"\n"<<"距离最小值为"<

cout<<"\n"<<"距离最小值的第一个点为"<

}

if(sum%10!=0)

{

k=sum/10;

cout<<"输入0显示结果"<

cin>>i;

for(i=1;i

{

for(j=0;j

{

m=abs(p[k*10+i].x-p[k*10+j].x);

n=abs(p[k*10+i].y-p[k*10+j].y);

juli[i][j]=sqrt(m*m+n*n);

cout<

cout<<"\t";

}

cout<

}

min[k]=juli[1][0],mini[k]=10*k+1,minj[k]=10*k;

for(i=1;i

{

cout<<"\n"<<"第"<

for(j=0;j

{

if(juli[i][j]

{

min[k]=juli[i][j];

mini[k]=10*k+i;

minj[k]=10*k+j;

}

}

}

cout<<"\n"<<"这是第"<

cout<<"\n"<<"距离最小值为"<

cout<<"\n"<<"距离最小值的第一个点为"<

}

}

void realmin()

{

cout<<"\n"<<"几个模块中的最小值是:"<

for(i=0,min[10]=min[0],mini[10]=mini[0],minj[10]=minj[0];i<=sum/10;i++)

{

if(min[i]

{

min[10]=min[i];

mini[10]=mini[i];

minj[10]=minj[i];

}

}

}

void bianjiemin()

{

cout<<"\n"<<" 包括边界的最小值是:"<

for(i=0;i

{

for(k=9;k>=0;k--)

if(p[(i+1)*10].x-p[i*10+k].x

{

for(q=0;q<10;q++)

if(p[(i+1)*10+m].x-p[(i+1)*10].x

{

m=abs(p[i*10+k].x-p[(i+1)*10+m].x);

n=abs(p[i*10+k].y-p[(i+1)*10+m].y);

if(min[10]>sqrt(m*m+n*n))

{

min[10]=sqrt(m*m+n*n);

mini[10]=i*10+k;

minj[10]=(i+1)*10+q;

}

}

else

break;

}

else

break;

}

}

void shuchu()

{

i=mini[10];

j=minj[10];

p2= abs(p[i].x-p[j].x)*abs(p[i].x-p[j].x) ;

q= abs(p[i].x-p[j].x)*abs(p[i].x-p[j].x) ;

s=sqrt(p2+q);

cout<<"\n"<<"最接近点对为"<<"p["<

cout<<"\n"<<"最短距离为"<

cout<<"\n"<<"最短距离为"<

}

};

int main()

{

Ppoint x;

x.shuru();

x.sort();

x.xiao();

x.realmin();

x.bianjiemin();

x.shuchu();

return 0;

}

二.设计体会

通过这次的课程设计,我对C++程序语言有了更进一步的认识。我运用C++程序语言进行编程的能力有一定程度的提高,也掌握了C++程序语言程序设计过程、方法及实现,为以后相关的课程的学习打下良好基础;培养了我分析、解决问题的能力;也提高了我课程设计论文的写作能力。

此次课程设计也让我发现了自己有许多的不足之处.由于平时的编写程序的机会也不是很多,再加上自己对C++程序语言掌握的不是很全面,使我设计程序的过程中遇到了一些难题.最后还得求助于书本才得以将问题解决.所以,我认为自己的实际编写程序能力还有待加强.

在课程设计的过程当中,程序的设计中运用到了C++程序语言中的类设计与实现、函数调用等方面的知识,从而使我更进一步地了解了那些方面的知识.我设计了学生选修课程系统设计和用分治算法解平面最接近点对问题这两个程序,经过查阅各种书籍以及上网查询,我基本能够实现老师所要求实现的功能.

总之,通过这次C++程序语言的课程设计,我不但在C++的理论知识方面有所提高,而且在实际应用方面也有一定的提高!以后我也会更加努力的学习有关C++以及相关的知识,以使自己更加理解C++程序语言并会运用其编出更好的程序!

三、参考文献

钱能<> 清华大学出版社

陈志泊王春玲<<面向对象的程序设计语言-C++>> 人民邮电出版

网站:https://www.360docs.net/doc/6214282533.html,

算法分析与设计习题集整理

算法分析与设计习题集整理 第一章算法引论 一、填空题: 1、算法运行所需要的计算机资源的量,称为算法复杂性,主要包括时间复杂度和空间复杂度。 2、多项式10()m m A n a n a n a =+++L 的上界为O(n m )。 3、算法的基本特征:输入、输出、确定性、有限性 、可行性 。 4、如何从两个方面评价一个算法的优劣:时间复杂度、空间复杂度。 5、计算下面算法的时间复杂度记为: O(n 3) 。 for(i=1;i<=n;i++) for(j=1;j<=n;j++) {c[i][j]=0; for(k=1;k<=n;k++) c[i][j]= c[i][j]+a[i][k]*b[k][j]; } 6、描述算法常用的方法:自然语言、伪代码、程序设计语言、流程图、盒图、PAD 图。 7、算法设计的基本要求:正确性 和 可读性。 8、计算下面算法的时间复杂度记为: O(n 2) 。 for (i =1;i

算法设计与分析:递归与分治法-实验报告

应用数学学院信息安全专业班学号姓名 实验题目递归与分治法 综合实验评分表

实验报告 一、实验目的与要求 1.掌握递归算法的设计思想 2.掌握分治法设计算法的一般过程 3.理解并掌握算法渐近时间复杂度的分析方法 二、实验内容 1、折半查找的递归算法 (1)源程序代码 #include #include using namespace std; int bin_search(int key[],int low, int high,int k) { int mid; if(low>high) return -1; else{ mid = (low+high) / 2; if(key[mid]==k) return mid; if(k>key[mid]) return bin_search(key,mid+1,high,k); else return bin_search(key,low,mid-1,k); } } int main() { int n , i , addr; int A[10] = {2,3,5,7,8,10,12,15,19,21}; cout << "在下面的10个整数中进行查找" << endl; for(i=0;i<10;i++){ cout << A[i] << " " ; } cout << endl << endl << "请输入一个要查找的整数" << endl; cin >> n; addr = bin_search(A,0,9,n);

if(-1 != addr) cout << endl << n << "是上述整数中的第" << addr << "个数" << endl; else cout << endl << n << "不在上述的整数中" << endl << endl; getchar(); return 0; } (2)运行界面 ①查找成功 ②查找失败

算法分析实验报告--分治策略

《算法设计与分析》实验报告 分治策略 姓名:XXX 专业班级:XXX 学号:XXX 指导教师:XXX 完成日期:XXX

一、试验名称:分治策略 (1)写出源程序,并编译运行 (2)详细记录程序调试及运行结果 二、实验目的 (1)了解分治策略算法思想 (2)掌握快速排序、归并排序算法 (3)了解其他分治问题典型算法 三、实验内容 (1)编写一个简单的程序,实现归并排序。 (2)编写一段程序,实现快速排序。 (3)编写程序实现循环赛日程表。设有n=2k个运动员要进行网球循环赛。现 要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其它n-1个选手各赛一次(2)每个选手一天只能赛一场(3)循环赛进行n-1天 四、算法思想分析 (1)编写一个简单的程序,实现归并排序。 将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行 排序,最终将排好序的子集合合并成为所要求的排好序的集合。 (2)编写一段程序,实现快速排序。 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有 数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数

据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

(3)编写程序实现循环日赛表。 按分治策略,将所有的选手分为两组,n个选手的比赛日程表就可以通 过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割, 直到只剩下2个选手时,比赛日程表的制定就变得很简单。这时只要让 这2个选手进行比赛就可以了。 五、算法源代码及用户程序 (1)编写一个简单的程序,实现归并排序。 #include #include #define MAX 10 using namespace std; void merge(int array[],int p,int q,int r) { int i,k; int begin1,end1,begin2,end2; int* temp = new int[r-p+1]; begin1 = p; end1 = q; begin2 = q+1; end2 = r; k = 0; while((begin1 <= end1)&&(begin2 <= end2)) { if(array[begin1] < array[begin2])

分治算法例题

目录 1031 输油管道问题 (2) 解题思路 (2) 程序代码 (2) 1032 邮局选址 (5) 解题思路 (5) 程序源代码 (5) 1034 集合划分2 (7) 解题思路: (7) 程序源代码: (7) 1033 集合划分 (9) 解题思路 (9) 程序源代码 (9)

1031 输油管道问题 解题思路 本题目可以分为两个步骤: 1、找出主管道的位置; 2、根据主管道的位置,计算各个油井到主管道的长度之和。 根据题意,设主管道贯穿东西,与y 轴平行。而各个子油井则分布在主输油管道的上下两侧。如下图: 由上图,其实只需要确定主管道的y 坐标,而与各个子油井的x 坐标无关!根据猜测,易知:主管道的y 坐标就是所有子油井y 坐标的中位数。(可以用平面几何知识证明,略) 求中位数的方法可以用排序后取a[(left+right)/2],当然更推荐用书上的线性时间选择算法解决。记求得的主管道为m y ,最后要输出的结果只需要计算:1||n i m i y y =-∑,输出即可。 另外要提醒的是本题多Case 。 程序代码 #include #include void swap (int &a ,int &b ) { int tmp = a ; a = b ; b = tmp ; }

//本函数求arr[p:q]的一个划分i,使arr[p:i-1]都小于arr[i],arr[i+1,q]都大于arr[i] int partition(int *arr,int p,int q) { int index = p-1,start = p,base = arr[q]; for(;start

分治算法实验(用分治法实现快速排序算法)

算法分析与设计实验报告第四次附加实验

while (a[--j]>x); if (i>=j) { break; } Swap(a[i],a[j]); } a[p] = a[j]; //将基准元素放在合适的位置 a[j] = x; return j; } //通过RandomizedPartition函数来产生随机的划分 template vclass Type> int RandomizedPartition(Type a[], int p, int r) { int i = Random(p,r); Swap(a[i],a[p]); return Partition(a,p,r); } 较小个数排序序列的结果: 测试结果 较大个数排序序列的结果:

实验心得 快速排序在之前的数据结构中也是学过的,在几大排序算法中,快速排序和归并排序尤其是 重中之重,之前的快速排序都是给定确定的轴值,所以存在一些极端的情况使得时间复杂度 很高,排序的效果并不是很好,现在学习的一种利用随机化的快速排序算法,通过随机的确 定轴值,从而可以期望划分是较对称 的,减少了出现极端情况的次数,使得排序的效率挺高了很多, 化算法想呼应,而且关键的是对于随机生成函数,通过这一次的 学习终于弄明白是怎么回事了,不错。 与后面的随机实 验和自己的 实验得分助教签名 附录: 完整代码(分治法) //随机后标记元素后的快速排序 #i nclude #in elude #inelude #include using namespacestd; template < class Type> void S &x,Type &y); // 声明swap函数 inline int Random(int x, int y); // 声明内联函数 template < class Type> int Partition(Type a[], int p, int r); // 声明 Partition 函数template int RandomizedPartition(Type a[], int p, int r); // 声明 RandomizedPartition 函数 int a[1000000]; //定义全局变量用来存放要查找的数组 更大个数排序序列的结果:

算法之2章递归与分治

算法分析(第二章):递归与分治法 一、递归的概念 知识再现:等比数列求和公式: 1、定义:直接或间接地调用自身的算法称为递归算法。 用函数自身给出定义的函数称为递归函数。 2、与分治法的关系: 由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归经常同时应用在算法设计之中,并由此产生许多高效算法。 3、递推方程: (1)定义:设序列01,....n a a a简记为{ n a},把n a与某些个() i a i n <联系起来的等式叫做关于该序列的递推方程。 (2)求解:给定关于序列{n a}的递推方程和若干初值,计算n a。 4、应用:阶乘函数、Fibonacci数列、Hanoi塔问题、插入排序 5、优缺点: 优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大方便。 缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归算法要多。 二、递归算法改进: 1、迭代法: (1)不断用递推方程的右部替代左部 (2)每一次替换,随着n的降低在和式中多出一项 (3)直到出现初值以后停止迭代 (4)将初值代入并对和式求和 (5)可用数学归纳法验证解的正确性 2、举例: -----------Hanoi塔算法----------- ---------------插入排序算法----------- ()2(1)1 (1)1 T n T n T =?+ = ()(1)1 W n W n n W =?+? (1)=0

算法分析实验报告--分治策略

分治策略 姓名:XXX 专业班级:XXX 学号:XXX 指导教师:XXX 完成日期:XXX

一、试验名称:分治策略 (1)写出源程序,并编译运行 (2)详细记录程序调试及运行结果 二、实验目的 (1)了解分治策略算法思想 (2)掌握快速排序、归并排序算法 (3)了解其他分治问题典型算法 三、实验内容 (1)编写一个简单的程序,实现归并排序。 (2)编写一段程序,实现快速排序。 (3)编写程序实现循环赛日程表。设有n=2k个运动员要进行网球循环赛。现 要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其它n-1个选手各赛一次(2)每个选手一天只能赛一场(3)循环赛进行n-1天 四、算法思想分析 (1)编写一个简单的程序,实现归并排序。 将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行 排序,最终将排好序的子集合合并成为所要求的排好序的集合。 (2)编写一段程序,实现快速排序。 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有 数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数 据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据 变成有序序列。 (3)编写程序实现循环日赛表。 按分治策略,将所有的选手分为两组,n个选手的比赛日程表就可以通 过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割, 直到只剩下2个选手时,比赛日程表的制定就变得很简单。这时只要让

这2个选手进行比赛就可以了。 五、算法源代码及用户程序 (1)编写一个简单的程序,实现归并排序。 #include #include<> #define MAX 10 using namespace std; void merge(int array[],int p,int q,int r) { int i,k; int begin1,end1,begin2,end2; int* temp = new int[r-p+1]; begin1 = p; end1 = q; begin2 = q+1; end2 = r; k = 0; while((begin1 <= end1)&&(begin2 <= end2)) { if(array[begin1] < array[begin2]) { temp[k] = array[begin1]; begin1++; } else { temp[k] = array[begin2]; begin2++; } k++; } while(begin1 <= end1) { temp[k++] = array[begin1++]; }

递归与分治实验报告

递归与分治实验报告 班级:计科1102 姓名:赵春晓学号:2011310200631 实验目的:进一步掌握递归与分治算法的设计思想,通过实际问题来应用递归与分治设计算法。 实际问题:1集合划分问题,2输油管道问题,3邮局选址问题,4整数因子分解问题,5众数问题。 问题1:集合划分 算法思想:对于n个元素的集合,可以划分为由m个子集构成的集合,例如{{1,2}{3,4}}就是由2个子集构成的非空子集。假设f(n,m)表示将n个元素划分成由m个子集构成的集合的个数。那么1)若m == 1 ,则f(n,m)= 1 ;2)若n == m ,则f(n,m)= 1 ;3)若不是上面两种情况则有下面两种情况构成:3.1)向n-1个元素划分成的m个集合里面添加一个新的元素,则有m*f(n-1,m)种方法;3.2)向n-1个元素划分成的m-1个集合里添加一个由一个元素形成的独立的集合,则有f(n-1,m-1)种方法。 实验代码: #include #include using namespace std ; int jihehuafen( int n , int m ) { if( m == 1 || n == m ) return 1 ; else return jihehuafen( n - 1 , m - 1 ) + m*jihehuafen( n - 1 , m ) ; } int main() { ifstream fin("C:/input.txt") ; ofstream fout("C:/output.txt") ; int N , M , num ; fin >> N >> M ; num = jihehuafen( N , M) ; fout << num << endl ; return 0 ; } 问题2:输油管道 算法思想:由于主管道由东向西铺设。故主管道的铺设位置只和各油井的y坐标有关。要使主管道的y坐标最小,主管道的位置y坐标应是各个油井y坐标的中位数。先用快速排序法把各个油井的y坐标排序,然后取其中位数再计算各个油

大学算法分析与设计复习总结

大学算法分析与设计复习总结 第1章绪论 考点: 1、算法的5个重要特性。(P3) 答:输入、输出、有穷性、确定性、可行性 2、描述算法的四种方法分别是什么,有什么优缺点。(P4) 答: 1.自然语言优点:容易理解;缺点:容易出现二义性,并且算法都很冗长。 2.流程图优点:直观易懂;缺点:严密性不如程序语言,灵活性不如自然语言。 3.程序设计语言优点:用程序语言描述的算法能由计算机直接执行;缺点:抽象性差,是算法设计者拘泥于描述算法的具体细节,忽略了“好”算法和正确逻辑的重要性,此外,还要求算法设计者掌握程序设计语言及其编程技巧。 4.伪代码优点:表达能力强,抽象性强,容易理解 3、了解非递归算法的时间复杂性分析。(P13) 要点:对非递归算法时间复杂性的分析,关键是建立一个代表算法运行时间的求和表达式,然后用渐进符号表示这个求和表达式。 非递归算法分析的一般步骤是: (1)决定用哪个(或哪些)参数作为算法问题规模的度量。 (2)找出算法的基本语句。 (3)检查基本语句的执行次数是否只依赖问题规模。 (4)建立基本语句执行次数的求和表达式。 (5)用渐进符号表示这个求和表达式。

[例1.4]:求数组最小值算法 int ArrayMin(int a[ ], int n) { min=a[0]; for (i=1; i

通用分支递归式: 使用扩展递归技术求解下列递推关系式(1) (2)

算法设计与分析习题答案1-6章

习题1 1. 图论诞生于七桥问题。出生于瑞士的伟大数学家欧拉(Leonhard Euler ,1707—1783)提出并解决了该问题。七桥问题是这样描述的:一个人是否能在一次步行中穿越哥尼斯堡(现在 叫加里宁格勒,在波罗的海南岸)城中全部的七座桥后回到起点,且每座桥只经过一次,图是这条河以及河上的两个岛和七座桥的草图。请将该问题的数据模型抽象出来,并判断此问题是否有解。 七桥问题属于一笔画问题。 输入:一个起点 输出:相同的点 1, 一次步行 2, 经过七座桥,且每次只经历过一次 3, 回到起点 该问题无解:能一笔画的图形只有两类:一类是所有的点都是偶点。另一类是只有二个奇点的图形。 2.在欧几里德提出的欧几里德算法中(即最初的欧几里德算法)用的不是除法而是减法。请用伪代码描述这个版本的欧几里德算法 =m-n 2.循环直到r=0 m=n n=r r=m-n 图 七桥问题 南区

3 输出m 3.设计算法求数组中相差最小的两个元素(称为最接近数)的差。要求分别给出伪代码和C++描述。 编写程序,求n至少为多大时,n个“1”组成的整数能被2013整除。 #include using namespace std; int main() { double value=0; for(int n=1;n<=10000 ;++n) { value=value*10+1; if(value%2013==0) { cout<<"n至少为:"< using namespace std; int main () {

实验1++递归与分治算法

淮海工学院计算机工程学院实验报告书 课程名:《算法分析与设计》 题目:实验1 递归与分治算法 班级: 学号: 姓名:

实验1 递归与分治算法 实验目的和要求 (1)进一步掌握递归算法的设计思想以及递归程序的调试技术; (2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。 (3)分别用蛮力法和分治法求解最近对问题; (4)分析算法的时间性能,设计实验程序验证分析结论。 实验内容 设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。 实验环境 Turbo C 或VC++ 实验学时 2学时,必做实验 数据结构与算法 核心源代码 蛮力法: #include #include #include int ClosestPoints(int x[ ], int y[ ], int n); int main() { int x[3],y[3]; printf("请输入各点的横坐标: "); for(int i=0;i<4;i++) { scanf("%d",&x[i]); } printf("请输入各点的纵坐标: "); for(int j=0;j<4;j++)

{ scanf("%d",&y[i]); } ClosestPoints(x,y,4); return 0; } int ClosestPoints(int x[ ], int y[ ], int n) { int index1, index2; //记载最近点对的下标 int d, minDist = 1000; //假设最大距离不超过1000 for (int i = 0; i < n - 1; i++) for (int j = i + 1; j < n; j++) //只考虑i<j的点对 { d =sqrt ((x[i]-x[j])* (x[i]-x[j]) + (y[i]-y[j])* (y[i]-y[j])); if (d < minDist) { minDist = d; index1 = i; index2 = j; } } cout<<"最近的点对是:"< #include const int n = 4; struct point //定义点的结构体 { int x, y; };

分治法--凸包

//纯代码 #include #define PPmax 30 typedef struct node { float x,y; }Point; Point DingDian[PPmax];//用于存放凸边形的顶点 int DingDnum=0; typedef struct Pointss { Point p1,p2; }SDian; SDian BDD[PPmax];//存放凸边形边的双点 int BDDnum=0;//记录已经存入的双点数 int abc=0;//全局变量,用来记录划边顺序 void dianxu(Point P[],int n) //对已经输入的点数组进行排序 {//存放点的数组P[], 点的个数n // ——点排序 // 具体实现:(选择排序实现) // 1.按x坐标从小到大排 // 2.扫描最前端点元素 // 2.1若不存在相同x坐标的点,则执行3 // 2.2若存在相同x坐标的点,按|y|排列大->小 // 3.扫描最后端点元素 // 3.1若不存在相同x坐标的点,则执行4 // 3.2若存在相同x坐标的点,按|y|排列小->大 // 4.返回。 Point temp; int i,j; int min,max; float px; int pxnum; //按x坐标排序 for(i=0;i<=n-2;i++) { min=i; for(j=i+1;j<=n-1;j++) { if(P[j].x

{ min=j; } } temp=P[i]; P[i]=P[min]; P[min]=temp; } //数组两端相同x按|y|排序 //前端排序 px=P[0].x; pxnum=1; while(P[pxnum].x==px) { pxnum++; } for(i=0;i<=pxnum-2;i++) { //max=i; min=i; for(j=i+1;j<=pxnum-1;j++) { if( P[j].y < P[min].y ) { min=j; } } temp=P[i]; P[i]=P[min]; P[min]=temp; } //后端排序 px=P[n-1].x; pxnum=1; while(P[n-1-pxnum].x==px) { pxnum++; } for(i=n-pxnum;i<=n-2;i++) { min=i;

算法分析与设计实验一递归与分治策略

实验一递归与分治策略 实验目的 1.了解并掌握递归的概念,递归算法的基本思想; 2.掌握分治法的基本思想方法; 3.了解适用于用分治法求解的问题类型,并能用递归或非递归的方式设计相应的分治法算法; 4.掌握分治法复杂性分析方法,比较同一个问题的递归算法与循环迭代算法的效率。预习与实验要求 1.预习实验指导书及教材的有关内容,掌握分治法的基本思想; 2.严格按照实验内容进行实验,培养良好的算法设计和编程的习惯; 3.认真听讲,服从安排,独立思考并完成实验。 实验原理 简单说来,当一个函数用它自己来定义时就称为递归。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。因此,在考虑使用递归算法编写程序时,应满足两点:1)该问题能够被递归形式描述;2)存在递归结束的边界条件。递归的能力在于用有限的语句来定义对象的无限集合。用递归思想写出的程序往往十分简洁易懂。一般说来,一个递归算法可以转换称为一个与之等效的非递归算法,但转换后的非递归算法代码将成倍地增加。 分治是一种被广泛应用的有效方法,它的基本思想是把最初的问题分解成若干子问题,然后在逐个解决各个子问题的基础上得到原始问题的解。所谓分治就是“分而治之”的意思。由于分解出的每个子问题总是要比最初的问题容易些,因而分治策略往往能够降低原始问题的难度,或者提高解决原始问题的效率。 根据如何由分解出的子问题求出原始问题的解,分治策略又可分为两种情形:第一,原始问题的解只存在于分解出的某一个子问题中,则只需要在原始问题的一个划分中求解即可;第二,原始问题的解需要由各个子问题的解再经过综合处理得到。无论是哪一种情况,分治策略可以较快地缩小问题的求解范围,从而加快问题求解的速度。 分治策略运用于计算机算法是,往往会出现分解出来的子问题与原始问题类型相同的现象,而与原问题相比,各个子问题的规模变小了,这刚好符合递归的特征。因此分治策略往往是和递归联系在一起的。

分治法解决凸包问题

#include typedef struct { int x,y; }Point; int arrayLength=0; int main() { printf("**************软件工程3班**************"); printf("*****************成冠辉*****************"); Point array[15],result[15]; InitialData(array); printf("请输入数据:\n\n"); Put(array,arrayLength); Qsort(array,0,arrayLength-1); printf("排序后:\n"); Put(array,arrayLength); GetResult(array,result); printf("结果集为:\n"); Put(result,resultCount); getchar(); return 0; } //返回分裂位置 int Partition(Point *array,int l,int r) { int p=l,i=l,j=r+1; do { do { i++; }while(array[i].x

j--; }while(array[j].x>array[p].x); swap(array,i,j); }while(iarray[14]射线左边的点DealWithLeft(14,0,array,result); //处理array[14]->array[0]射线右边的点} void InitialData(Point *array) { FILE *fp=freopen("input.txt","r",stdin); char ch;

分治算法

《算法设计与分析》实验报告 实验1 分治算法 一、实验目的 1、掌握分治算法的设计思想与分析方法; 2、掌握归并排序、快速排序等高效排序算法。 二、实验环境 1、硬件环境 CPU:Intel(R) Celeron(R) CPU 1007U @ 1.5GHz 内存:4G 硬盘:500G 2、软件环境 操作系统:Windows7 编程环境:Visual C++ 6.0 编程语言:C++ 三、实验内容 1、编写程序,实现归并排序算法。 (1)归并排序算法 归并排序(Merge Sort)是利用“归并”技术来进行排序。归并是将若干个已排序的子序列合并成一个有序的序列,两路归并算法基本思路为设两个有序的子文件(相当于输入堆)放在同一向量中相邻的位置上:R[low..m],R[m+1..high]。R[low..high]中。 合并过程中,设置i,j和p三个指针,其初值分别指向这三个记录区的起始位置。合并时依次比较R[i]和R[j]的关键字,取关键字较小的记录复制到R1[p]中,然后将被复制记录的指针i或j加1,以及指向复制位置的指针P加1。重复这一过程直至两个输入的子文件有一个已经全部复制完毕,此时将另一个非空的子文件中剩余记录一次复制到R1中即可。

(2)归并排序算法分析 时间复杂度:O(nlog2n) 空间复杂度:O(n) (3)编程要求 ●待排序数组长度至少为16,数组中可以有相同元素; ●按递增排序。 (4)程序代码(含注释) #include #define MAX_OF_ARRAY 20 //打印数据 void PrintArray(int *arrays) { for(int i=0;i void Merge(T c[],T d[],int l,int m,int r) { //把c[l:m]和c[m:r]归并到d[l:r] int i=l,j=m+1,k=l; while((i<=m)&&(j<=r)) { if(c[i]<=c[j]) d[k++]=c[i++]; else d[k++]=c[j++];

0007算法笔记——【分治法】最接近点对问题

问题场景:在应用中,常用诸如点、圆等简单的几何对象代表现实世界中的实体。在涉及这些几何对象的问题中,常需要了解其邻域中其他几何对象的信息。例如,在空中交通控制问题中,若将飞机作为空间中移动的一个点来看待,则具有最大碰撞危险的2架飞机,就是这个空间中最接近的一对点。这类问题是计算几何学中研究的基本问题之一。 问题描述:给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小。严格地说,最接近点对可能多于1对。为了简单起见,这里只限于找其中的一对。 1、一维最接近点对问题 算法思路: 这个问题很容易理解,似乎也不难解决。我们只要将每一点与其他n-1个点的距离算出,找出达到最小距离的两个点即可。然而,这样做效率太低,需要O(n^2)的计算时间。在问题的计算复杂性中我们可以看到,该问题的计算时间下界为Ω(nlogn)。这个下界引导我们去找问题的一个θ(nlogn)算法。采用分治法思想,考虑将所给的n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点,然后在每个子集中递归地求其最接近的点对。在这里,一个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对,因为S1和S2的最接近点对未必就是S的最接近点对。如果组成S的最接近点对的2个点都在S1中或都在S2中,则

问题很容易解决。但是,如果这2个点分别在S1和S2中,则对于S1中任一点p,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需做n^2/4次计算和比较才能确定S的最接近点对。因此,依此思路,合并步骤耗时为O(n^2)。整个算法所需计算时间T(n)应满足: T(n)=2T(n/2)+O(n^2)。它的解为T(n)=O(n^2),即与合并步骤的耗时同阶,这不比用穷举的方法好。从解递归方程的套用公式法,我们看到问题出在合并步骤耗时太多。这启发我们把注意力放在合并步骤 上。 设S中的n个点为x轴上的n个实数x1,x2,..,xn。最接近点对即为这n个实数中相差最小的2个实数。我们显然可以先将x1,x2,..,x n排好序,然后,用一次线性扫描就可以找出最接近点对。这种方法主要计算时间花在排序上,在排序算法已经证明,时间复杂度为O(nlogn)。然而这种方法无法直接推广到二维的情形。因此,对这种一维的简单情形,我们还是尝试用分治法来求解,并希望能推广到二维的情形。假设我们用x轴上某个点m将S划分为2个子集S1和S2,使得S1={x∈S|x≤m};S2={x∈S|x>m}。这样一来,对于所有p∈S1和q∈S2有p

实验一 递归与分治策略算法设计与实现实验报告

华北水利水电学院算法分析与设计实验报告 20010~2011学年第二学期2008级计算机科学与技术专业 班级:2008109 学号:200810906 姓名:刘景超 实验一递归与分治算法的设计与实现 一、实验目的: 1、了解递归、分治算法的设计思路与设计技巧,理解递归的概念,掌握设计有效算法的 分治策略。 2、通过实际案例,领会算法的执行效率 二、试验内容: 棋盘覆盖、最接近点对、排序算法、矩阵乘法等,(也可选作其它问题); 三、核心程序源代码: #include #include void main() { void hanoi(int n,char one,char two,char three); int m; cout<<"请输入要移动的盘子的数目:"<>m; cout<<"盘子的数目为:"<"<

五、小结 本想用MFC采用图形的方式展示移动的过程,可惜水平有限,实在是写不出来,只好采用控制台程序了。采用控制台程序表述还是很简单的,算法也不复杂。这次实验让我认识到我在MFC方面基础还很薄弱,还需要多多练习,慢慢提升自己。

分治算法作业

解: 根据分治的思想: (1) 在两个大小为你的数组A,B中取中位数,分别为m,n ,所用时间为 O(1);(2)比较m和n 的大小: 若m=n, return m,即返回m为中位数; 若mn,则取保留A的小于等于其下中位数部分,和B中大于等于其下中位数部分,分别组成新的数组,重新调用自己; (3)按照上述算法执行,直到找到中位数。 (4)所需时间T(n)满足:T(n) = T(n/2)+O(1) 根据master定理,可知其时间复杂性为:O(log(n)) 具体的算法: 两个等长数组求中位数 n←length[X] ?数组Y的长度也是n median ←Find_Median(Y,X,n,1,n) if median = NOT_FOUND then median← Find_Median(Y,X,n,1,n) return median Find_Median(A,B,n,low,high) if low>high then return NOT_FOUND else k←?(low+high)/2? if k = n and A[n]≤ B[1] then return A[n] elseif k< n and B[n - k] ≤ A[k] ≤ B[n – k + 1]

then return A[k] elseif A[k]> B[n-k+1] then return Find_Median(A,B,n,low,k-1) else return Find_Median(A,B,n,k+1,high) int Two_Array_Median( X[], Y[]) { n=length(X[]); int median= Find_Median(X[],Y[],n,1,n); if(median==0) median=Find_Median(Y[],X[],n,1,n); return median; } int FindMedian(A[],B[], n, low, high) { if(low>high) return 0; else { k=floor((low+high)/2); if(k==n && A[n]<=B[1]) return A[n]; else if(k=A[k]) return A[k]; else if(A[k]>B[n-k+1]) return FindMedian(A[],B[],n,low,k-1); else return FindMedian(A[],B[],n,k+1,high); } } 2、设A[1 : n]是由不同实数组成的数组,如果i < j 且A[i]>A[j],则称实数对(A[i], A[j])是该数组的一个反序。如,若A=[3,5,2,4],则该数组存在3 个反序(3,2)、(5,2)和(5,4)。反序的个数可以用来衡量一个数组的无序程度。设计一个分治算法(要求时间复杂度严格低于n2),计算给定数组的反序个数。答案要求包含以下内容: (1)用简明的自然语言表述算法的基本思想; (2)用伪代码描述算法; (3)分析算法的时间复杂度。 解:本算法改自合并排序: (1)算法改自合并排序,主要的改动在于Merge2的while循环,按照分治的思想,将原数组分成两个数组,两个数组中的元素进行比较之后,如果right[j]

相关文档
最新文档