算法分析——分治法

算法分析——分治法
算法分析——分治法

分治算法

小组的汇报内容:

一、分治算法的基本概念 (2)

二、分治算法的基本思想及策略 (2)

三、分治法适用的情况 (3)

四、分治法的基本步骤 (3)

五、分治法的复杂性分析 (4)

六、快速傅里叶变换 (5)

七、可使用分治法求解的一些经典问题 (9)

八、依据分治法设计程序时的思维过程 (9)

九、分治法与其它常见算法的比较 (9)

小组的分工情况:

彭勇讲前五个部分,天西山讲第六个部分,胡化腾讲最后三个部分,吕璐负责汇报的资料收集,小组分工以及最后的资料整理。

三、分治法适用的情况

分治法所能解决的问题一般具有以下几个特征:

1) 该问题的规模缩小到一定的程度就可以容易地解决

2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。

3) 利用该问题分解出的子问题的解可以合并为该问题的解;

4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;

第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;、

第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。

第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。

四、分治法的基本步骤

分治法在每一层递归上都有三个步骤:

step1 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;

step2 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题

step3 合并:将各个子问题的解合并为原问题的解。

它的一般的算法设计模式如下:

Divide-and-Conquer(P)

1. if |P|≤n0

2. then return(ADHOC(P))

3. 将P分解为较小的子问题 P1 ,P2 ,...,Pk

4. for i←1 to k

5. do yi ← Divide-and-Conquer(Pi) △递归解决Pi

6. T ← MERGE(y1,y2,...,yk) △合并子问题

7. return(T)

其中|P|表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。ADHOC(P)是该分治法中的基本子算法,用于直接解小规模的问题P。因此,当P的规模不超过n0时直接用算法ADHOC(P)求解。算法MERGE(y1,y2,...,yk)是该分治法中的合并子算法,用于将P的子问题P1 ,P2 ,...,Pk的相应的解y1,y2,...,yk合并为P的解。

五、分治法的复杂性分析

一个分治法将规模为n的问题分成k个规模为n/m的子问题去解。设分解阀值n0=1,且adhoc解规模为1的问题耗费1个单位时间。再设将原问题分解为k个子问题以及用merge将k个子问题的解合并为原问题的解需用f(n)个单位时间。用T(n)表示该分治法解规模为|P|=n的问题所需的计算时间,则有: T(n)= k T(n/m)+f(n)

通过迭代法求得方程的解:

递归方程及其解只给出n等于m的方幂时T(n)的值,但是如果认为T(n)足够平滑,那么由n等于m的方幂时T(n)的值可以估计T(n)的增长速度。通常假定T(n)是单调上升的,从而当mi≤n

在了解这个算法之前,我们首先必须弄清楚这样几个问题。什么是傅里叶变换?什么是快速傅里叶变换?

傅里叶变换能将满足一定条件的某个函数表示成三角函数(正弦和/或余弦函数)或者它们的积分的线性组合。在不同的研究领域,傅里叶变换具有多种不同的变体形式,如连续傅里叶变换和离散傅里叶变换。最初傅里叶分析是作为热过程的解析分析的工具被提出的。离散傅里叶变换的一种快速算法。所以我们可以了解到快速傅里叶变换就是对离散的点进行处理的算法。今天我们通过两个多项式的乘积来介绍FFT。

S=P X?K(X)

S=(P O+P1X+P2X2+?+P n?1X n?1)?(K0+K1X+K2X2+?+

K n?1X n?1)

在上个式子中,我们得到S是最高阶位2N-2。我们知道一次函数可以通过二个点来确定这个函数,二次函数可以通过三个点来确定,三次函数可以通过四个点来确定。由此我们可以推想S可以由2N-1个点上的值确定,事实上也确实如此,证明过程大家下去在研究。这2N-1个点上的值可以通过两个多项式在这些点上的值相乘而得到。由此我们得到两个N-1阶多项式相乘的一般方法,如下所示:

(1)计算给定的两个多项式在2N-1个不同点上的值。

(2)在没一点上将两值相乘。

(3) 根据这2N-1个点上的乘积,用内插法求出乘积多项式。

我们来计算这个算法的时间复杂度,可以得知其时间复杂度是N 2级别的。当N 很大时,已不能满足计算要求。必须寻找新的算法来解决这个问题。

下面我向大家介绍用快速傅里叶变换算法解决两个多项式的乘法问题,在算法中用到的思想就是分治的思想。

我们注意到刚才在用2N-1个点计算多项式成绩时,没有特别指定是什么点,只要他们在定义域内即可。这样,如果我们选取特点的2N-1个点,那么就有可能使计算多项式的值和内插变得容易。

可以选取1的复数跟W n 0、W n 1、…、W n n ?1来充当这些点。因为1的复数跟

具有周期变化的性质,所以这给计算带来了方便。可能大家已经忘记1的复数跟的表达形式了,我简要给大家介绍一下。

W n 0=cos 2kπ

n +sin 2kπ

n i (k=0、1、2……n-1)

这就是1的复数跟形式,具有周期性变化。我们就来验证一下。比如我们取一个多项式最高阶是7,那么它的复数跟就是。

W 80=1、W 81= 22+ 22i 、W 82=i 、W 83=? 22+ 22i W 84=1、W 85=?( 22+ 22i )、W 86=-i 、W 87=?(? 22+ 22

i ) 首先考虑用分治法计算多项式在1的复数跟上的值。即要计算多项式

S =(P O +P 1X +P 2X 2+?+P n ?1X n ?1)在点W n 0、W n 1、…、W n n ?1上的

值,表示为

y k = (n?1

i =0w n k )i p i ,0<=k

这时,(y 0、y 1、y 2…、y n ?1)称为(p 0、p 1、p 2…、p n ?1)的离散傅里叶变换,(p 0、p 1、p 2…、p n ?1)称为(y 0、y 1、y 2…、y n ?1)的傅里叶逆变换。

现在用法求多项式在W n k (0<=k

次幂和奇次幂两个子多项式。如n=8,则有

P X =P O +P 1X +P 2X 2+?+P 7X 7

=P O +P 2X 2+P 4X 4+P 6X 6+X (P 1+P 3X 2+P 5X 4+P 7X 6)

=P (X 2)+P 0(X 2)

若X 是1的复数根,则X 2也是1的复数根。即设X=W 80,则X 2=W 41,X 4=

W 42,X 3=W 43,这个计算带来了方便。

若n 是偶数,X 是1的n 次复数根,那么X 2必是1的n/2次方根,又由于P 0(X 2)和P (X 2)是n/2-1阶多项式,所以对P 0(X 2)和P (X 2)只要计算n/2个1的n/2次方根,从而节约了计算量。

比如计算7阶多项式,用一般方法就要计算P (x )在1的8次方根W 8,可以表示为如下:

W 8:W 80、W 81、W 82、W 83、?W 80、?W 81、?W 82、?W 83、

他们的平方是1的4次方根:

W 82:W 40、W 41、W 42、W 43、W 40、W 41、W 42、W 43

用分治法计算P (X )在n 个1的n 次方根上的值

P W n k =P(W n 2k )+P 0 (W n 2

k )

如7次多项式在8个1的8次方根上的值为:

P W 80 =P W 40 +W 80P 0 W 40

P W 81 =P W 41 +W 81P 0 W 41

P W 82 =P W 42 +W 82P 0 W 42

P W83=P W43+W83P0W43

P W84=P W44?W80P0W44

P W85=P W45?W81P0W45

P W86=P W46?W82P0W46

P W87=P W47?W83P0W47

设P(X)是n-1阶多项式,M(n)是计算P(X)在n个点上的值所需要的乘

法次数,M(n

2)是计算n

2

?1阶多项式在n

2

个点上的值所需要的乘法次数。由以上

讨论可得如下的地推关系式:

M(n)=2 M(n

2)+ n

2

(其中n

2

是求X?P0所需要的乘法次数。求解递归关系式

设n=2k

M2k 2k =

M2k?1

2k?1

+

1

2

?2?k?2k

M2k?1

=M2k?2

+

1

?2?k+1?2k?1

……

……

……

M20 20=

1

2

?2?0?20

M2k

=1

(2?k?2k+2?k+1?2k?1+?+2?0?20)

整理得:

M2k=1

2(2

0?2k+21?2k?1+?+2k?20)

=1

2

?k+1?2k

=1

2

n logn+1

可得M(n)=O(nlogn)。在n值很大时,nlogn比n2节省了很多运算次数,快速傅里叶变换具有很大的优势。

七、可使用分治法求解的一些经典问题

(1)二分搜索

(2)大整数乘法

(3)Strassen矩阵乘法

(4)棋盘覆盖

(5)合并排序

(6)快速排序

(7)线性时间选择

(8)最接近点对问题

(9)循环赛日程表

(10)汉诺塔

八、依据分治法设计程序时的思维过程

实际上就是类似于数学归纳法,找到解决本问题的求解方程公式,然后根据方程公式设计递归程序。

1、一定是先找到最小问题规模时的求解方法

2、然后考虑随着问题规模增大时的求解方法

3、找到求解的递归函数式后(各种规模或因子),设计递归程序即可。

九、分治法与其它常见算法的比较

1、递归与分治法:

由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。

分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许

多高效算法。

2、动态规划法与分治法

共同点:将待求解的问题分解成若干子问题,先求解子问题,然后再从这些子问题的解得到原问题的解。

不同点: 1、适合于用动态规划法求解的问题,分解得到的各子问题往往不是相互独立的;而分治法中子问题相互独立。

2、动态规划法用表保存已求解过的子问题的解,再次碰到同样的子问题时不必重新求解,而只需查询答案,故可获得多项式级时间复杂度,效率较高;而分治法中对于每次出现的子问题均求解,导致同样的子问题被反复求解,故产生指数增长的时间复杂度,效率较低。

最接近点对问题实验报告

最接近点对问题 一.实验目的: 1.理解算法设计的基本步骤及各步的主要内容、基本要求; 2.加深对分治设计方法基本思想的理解,并利用其解决现实生活中的问题; 3.通过本次实验初步掌握将算法转化为计算机上机程序的方法。 二.实验内容: 1.编写实现算法:给定n对点,在这n对点中找到距离最短的点对。 2.将输出数据存放到另一个文本文件中,包括结果和具体的运行时间。 3.对实验结果进行分析。 三.实验操作: 1.最接近点对查找的思想: 首先,将所有的点对按照x坐标排序,找到x坐标的中位数,将所有的点对分成三部分,横坐标小于x(S1)、等于x(S2)和大于x(S3)的点对,在求取每部分中的最短距离,利用分治法,一步步地分解为子问题,找到最短距离d。由于距离最近的两个点可能在不同的区域中,需要进一步判断。 选择S1中的一个点,由于与它相比较的点的距离不可能超过d,故其配对范围为d*2d的矩形,将这个矩形划分为6份2/d*3/d的小矩形,其对角线的长度为5/6d,小于d,故S1中的任意一个点只需和S2中的6个点比较即可,最终确定最短的距离。 2.取中位数: 为了减少算法的时间开销,需要将所有的点对进行分组,以中位数为基准,考虑到快速排序的不稳定性,本次排序使用了合并排序。 代码实现: template void Merge(Type c[],Type d[],int l,int m,int 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++]; } if(i>m) { for(int q=j; q<=r; q++) d[k++] = c[q]; } else{ for(int q=i; q<=m; q++) d[k++] = c[q]; } } template void MergeSort(Type a[],Type b[],int left,int right){ if(left

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

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

实验报告 一、实验目的与要求 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)运行界面 ①查找成功 ②查找失败

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

2009.1算法设计与分析课程期末试卷-A卷(自测 )

华南农业大学期末考试试卷(A卷)2008学年第一学期考试科目:算法分析与设计 考试类型:(闭卷)考试时间:120 分钟 学号姓名年级专业 一、选择题(20分,每题2分) 1.下述表达不正确的是。 A.n2/2 + 2n的渐进表达式上界函数是O(2n) B.n2/2 + 2n的渐进表达式下界函数是Ω(2n) C.logn3的渐进表达式上界函数是O(logn) D.logn3的渐进表达式下界函数是Ω(n3) 2.当输入规模为n时,算法增长率最大的是。 A.5n B.20log 2n C.2n2 D.3nlog 3 n 3.T(n)表示当输入规模为n时的算法效率,以下算法效率最优的是。A.T(n)= T(n – 1)+1,T(1)=1 B.T(n)= 2n2 C.T(n)= T(n/2)+1,T(1)=1 D.T(n)= 3nlog 2 n 4.在棋盘覆盖问题中,对于2k×2k的特殊棋盘(有一个特殊方块),所需的L型骨 牌的个数是。 A.(4k– 1)/3 B.2k /3 C.4k D.2k 5.在寻找n个元素中第k小元素问题中,若使用快速排序算法思想,运用分治算

法对n个元素进行划分,应如何选择划分基准?下面答案解释最合理。 A.随机选择一个元素作为划分基准 B.取子序列的第一个元素作为划分基准 C.用中位数的中位数方法寻找划分基准 D.以上皆可行。但不同方法,算法复杂度上界可能不同 6.有9个村庄,其坐标位置如下表所示: 现在要盖一所邮局为这9个村庄服务,请问邮局应该盖在才能使到邮局到这9个村庄的总距离和最短。 A.(4.5,0)B.(4.5,4.5)C.(5,5)D.(5,0) 7.n个人拎着水桶在一个水龙头前面排队打水,水桶有大有小,水桶必须打满水, 水流恒定。如下说法不正确? A.让水桶大的人先打水,可以使得每个人排队时间之和最小 B.让水桶小的人先打水,可以使得每个人排队时间之和最小 C.让水桶小的人先打水,在某个确定的时间t内,可以让尽可能多的人打上水D.若要在尽可能短的时间内,n个人都打完水,按照什么顺序其实都一样 8.分治法的设计思想是将一个难以直接解决的大问题分割成规模较小的子问题, 分别解决子问题,最后将子问题的解组合起来形成原问题的解。这要求原问题和子问题。

分别用蛮力法、分治法、减治法实现a的N次方

《算法设计与分析》实验报告一 学号:姓名: 日期: 2012.11.5 得分: 一、实验内容: 分别用蛮力法、分治法、减治法实现a^n。 二、实验要求: 完成试验报告、给出对此结果。 为防止大数溢出,可以用1^n来测试在n比较大是的三种算法运行情况。 四、源程序及注释: #include #include using namespace std; //蛮力法求a的n次方 int Power1(int a,int n) { int as=1; for(int i=0;i

} int main() { int a=1; int n=10000; LARGE_INTEGER start1,end1,start2,end2,start3,end3,f; QueryPerformanceFrequency(&f); QueryPerformanceCounter(&start1) ; int p1=Power1(a,n); QueryPerformanceCounter(&end1); QueryPerformanceCounter(&start2) ; int p2=Power2(a,n); QueryPerformanceCounter(&end2); QueryPerformanceCounter(&start3) ; int p3=Power3(a,n); QueryPerformanceCounter(&end3); cout<<"a="<

最近点对分治法

假设在一片金属上钻n 个大小一样的洞,如果洞太近,金属可能会断。若知道任意两个洞的最小距离,可估计金属断裂的概率。这种最小距离问题实际上也就是距离最近的点对问题。 如果不用分治法,问题非常容易解决。也就是蛮力法。 代码如下: #include #include typedef struct TYPE { double x, y; } Point; float dist(Point a,Point b) { return (float)sqrt((float)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } float nearest(Point* points, int n) { float temp,near1=10000; int i,j; if(n==1) { printf("不可能"); return 0; } else{ for(i=0; itemp)?temp:near1; } } return near1; } } int main()

{ int n, i; double d; printf("输入点的个数:"); scanf("%d", &n); Point a[10000]; while (n) { for (i = 0; i < n; i++) scanf("%lf%lf", &(a[i].x), &(a[i].y)); d = nearest(a,n); printf("%.2lf\n", d); scanf("%d", &n); } return 0; } 但是本题是用分治法,我也参考了网上很多资料,他们要求对纵坐标进行排序,可能是为了对求右边的问题的点扫描用for 循环,但我发现那算法就不对,但愿是我的还没有完全明白按纵坐标排序的原因, 我参考的资料: https://www.360docs.net/doc/9d5014238.html,/p-198711591.html?qq-pf-to=pcqq.c2c 代码如下: #include #include #include

算法设计与分析课程期末试卷-A卷(自测 )

华南农业大学期末考试试卷(A卷) 2008学年第一学期考试科目:算法分析与设计 考试类型:(闭卷)考试时间:120分钟 学号姓名年级专业 一、选择题(20分,每题2分) 1.下述表达不正确的是。 A.n2/2 + 2n的渐进表达式上界函数是O(2n) B.n2/2 + 2n的渐进表达式下界函数是Ω(2n) C.logn3的渐进表达式上界函数是O(logn) D.logn3的渐进表达式下界函数是Ω(n3) 2.当输入规模为n时,算法增长率最大的是。 A.5n B.20log2n C.2n2D.3nlog3n 3.T(n)表示当输入规模为n时的算法效率,以下算法效率最优的是。A.T(n)= T(n – 1)+1,T(1)=1 B.T(n)= 2n2 C.T(n)= T(n/2)+1,T(1)=1 D.T(n)= 3nlog2n 4.在棋盘覆盖问题中,对于2k×2k的特殊棋盘(有一个特殊方块),所需的L型骨 牌的个数是。 A.(4k– 1)/3 B.2k /3 C.4k D.2k 5.在寻找n个元素中第k小元素问题中,若使用快速排序算法思想,运用分治算法 对n个元素进行划分,应如何选择划分基准?下面答案解释最合理。A.随机选择一个元素作为划分基准 B.取子序列的第一个元素作为划分基准 C.用中位数的中位数方法寻找划分基准 D.以上皆可行。但不同方法,算法复杂度上界可能不同

6. 现在要盖一所邮局为这9个村庄服务,请问邮局应该盖在 才能使到邮局到这9个村庄的总距离和最短。 A .(4.5,0) B .(4.5,4.5) C .(5,5) D .(5,0) 7. n 个人拎着水桶在一个水龙头前面排队打水,水桶有大有小,水桶必须打满水, 水流恒定。如下 说法不正确? A .让水桶大的人先打水,可以使得每个人排队时间之和最小 B .让水桶小的人先打水,可以使得每个人排队时间之和最小 C .让水桶小的人先打水,在某个确定的时间t 内,可以让尽可能多的人打上水 D .若要在尽可能短的时间内,n 个人都打完水,按照什么顺序其实都一样 8. 分治法的设计思想是将一个难以直接解决的大问题分割成规模较小的子问题,分 别解决子问题,最后将子问题的解组合起来形成原问题的解。这要求原问题和子问题 。 A .问题规模相同,问题性质相同 B .问题规模相同,问题性质不同 C .问题规模不同,问题性质相同 D .问题规模不同,问题性质不同 9. 对布线问题,以下 是不正确描述。 A .布线问题的解空间是一个图 B .可以对方格阵列四周设置围墙,即增设标记的附加方格的预处理,使得算法简化对边界的判定 C .采用广度优先的标号法找到从起点到终点的布线方案(这个方案如果存在的话)不一定是最短的 D .采用先入先出的队列作为活结点表,以终点b 为扩展结点或活结点队列为空作为算法结束条件 10. 对于含有n 个元素的子集树问题,最坏情况下其解空间的叶结点数目为 。 A .n! B .2n C .2n+1-1 D . ∑=n i i n 1 !/! 答案:DACAD CACCB

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

《算法设计与分析》实验报告 分治策略 姓名: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) {

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

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

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]; //定义全局变量用来存放要查找的数组 更大个数排序序列的结果:

分治法

分治法 【摘要】:分治法可以通俗的解释为:把一片领土分解,分解为若干块小部分,然后一块块地占领征服,被分解的可以是不同的政治派别或是其他什么,然后让他们彼此异化。本文主要叙述了分治法的设计思想及与之有关的递归思想,了解使用分治法解决问题的过程。 【关键词】:分治法分解算法递归二分搜索 Partition Method (Junna Wei) 【abstract 】: the partition method can explain to popular: decomposition, put a slice of territory is decomposed into several pieces of small, then pieces of land occupation of conquest, the decomposition can be different political factions or something, then let them each other alienation. This paper mainly describes the design idea of the partition method and recursive thinking, related to understand the process of solving the problem using the partition method. 【key words 】: partition method decomposition algorithm recursive Binary search 1.引论

分治法实现快速排序与两路合并排序

实验报告 (2015 / 2016 学年第二学期) 课程名称 实验名称分治法实现快速排序与两路合并排序 实验时间年月日指导单位计算机学院计算机科学与技术系 指导教师 学生姓名班级学号 学院(系) 专业 实验报告

三、实验原理及内容 实验原理: 分治法:即分而治之。将问题分解为规模较小,相互独立,类型相同的问题进行求解。对于无序数组的有序排序也就是按某种方式将序列分成两个或多个子序列,分别进行排序,再将已排序的子序列合并成一个有序序列。 实验内容: 两路合并排序算法的基本思想是:将待排序元素序列一分为二,得到两个长度基本相等的子序列,其过程类似于对半搜索;然后将子序列分别排序,如果子序列较长,还可以继续细分,知道子序列长度不超过1为止。 以上的实现由下列代码执行: void SortableList::MergeSort() { MergeSort(0,n-1); } void SortableList::MergeSort(int left,int right) { if (left

分治法实现快速排序

实验一 实验名称:利用分治法实现快速排序 实验时 2012 年12月成绩: 间: 一、实验目的 分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各个子问题的解合并得到原问题的解。 本实验的目的是利用分治策略实现快速排序算法。 二、实验内容 快速排序算法是基于分治策略的排序算法。其基本思想是,对于输入的子数组a[p:r],按以下三个步骤进行排序。 (1)分解:以a[p]为基准元素将a[p:r]划分成3段a[p:q-1],a[q] 和a[q+1:r], 使a[p:q-1]中任何一个元素小于等于a[q],而a[q+1:r]中任何一个元素大于等于 a[q]。下标q在划分过程中确定。 (2)递归求解:通过递归调用快速排序算法分别对a[p:q-1]和a[q+1:r]进行排序。 (3)合并:由于对a[p:q-1]和a[q+1:r]的排序是就地进行的,所以在a[p:q-1] 和a[q+1:r]都已排好的序后,不需要执行任何计算,a[p:r]就已排好序。 基于这个思想,可实现的快速排序算法如下: void QuickSort(i nt a[],i nt p,i nt r) if(p

int q=Partition(a,p,r); QuickSort(a,p,q-1); QuickSort(a,q+1,r); } } 对含有n 个元素的数组a[0;n-1] 进行快速排序只要调用QuickSort(a,0,n-1) 即可。 上述算法中的函数Partition ,以确定的一个基准元素a[p] 对子数组a[p:r] 进行划分,它是快速排序算法的关键。 int Partition(int a[],int p,int r) { int i=p,j=r+1; int x=a[p]; while(true) { while(a[++i]x); if(i>=j) break; Swap(a[i],a[j]); } a[p]=a[j];

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

一. 用分治算法解平面最接近点对问题 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<<"请输入要处理的点的个数"<>sum; for(i=0;i

算法设计与分析答案

1. 按分治策略求解棋盘覆盖问题时,对于如图所示的24×24 的特殊棋盘,共需要多少个L 型骨 牌;并在棋盘上填写L 型骨牌的覆盖情况。 2. 假设有7个物品,给出重量和价值。若这些物品均不能被分割,且背包容量M =140,使用回 溯方法求解此0-1背包问题。请画出状态空间搜索树。 3. 假设有7个物品,它们的重量和价值如下表所示。若这些物品均可以被分割,且背包容量M =140,使用贪心算法求解此背包问题。请写出求解策略和求解过程。 W (35,30,50,60,40,10,25)p (10,40,30,50,35,40,30) 4. 在给出的电路板中,阴影部分是已作了封锁标记的方格,请按照队列式分支限界法在图中确定 a 到 b 的最短布线方案,要求布线时只能沿直线或直角进行,在图中标出求得最优解时各方格情况。 5. 画出字符表的哈夫曼编码对应的二叉树。 6. 已知1 ()*()i i k k ij r r A a +=,k =1,2,3,4,5,6,r 1=5,r 2=10,r 3=3,r 4=8,r 5=5,r 6=20,r 7=6,求 矩阵链积A 1×A 2×A 3×A 4×A 5×A 6的最佳求积顺序。 7. 给出城市网络图,售货员要从城市1出发,经过所有城市回到城市1,画出该问题的解空间树, 描述出用优先队列式分支限界法求解时的搜索情况。表示出优先队列、当前扩展结点等的变化情况。 8. 依据优先队列式分支限界法,求从s 点到t 点的单源最短路径,画出求得最优解的解空间树。 一、假设有7个物品,它们的重量和价值如下表所示。若这些物品均不能被分割,且背包容量M =150,使用回溯方法求解此背包问题。请写出状态空间搜索树(20分)。 答:按照单位效益从大到小依次排列这7个物品为:FBGDECA 。将它们的序号分别记为1~7。则可生产如下的状态空间搜索树。其中各个节点处的限界函数值通过如下方式求得:【排序1分】

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

分治策略 姓名: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++]; }

《计算机算法设计与分析》习题及答案.doc

《计算机算法设计与分析》习题及答案 一.选择题 1、二分搜索算法是利用( A )实现的算法。 A、分治策略 B、动态规划法 C、贪心法 D、回溯法 2、下列不是动态规划算法基本步骤的是( A )。 A、找出最优解的性质 B、构造最优解 C、算出最优解 D、定义最优解 3、最大效益优先是( A )的一搜索方式。 A、分支界限法 B、动态规划法 C、贪心法 D、回溯法 4. 回溯法解旅行售货员问题时的解空间树是( A )。 A、子集树 B、排列树 C、深度优先生成树 D、广度优先生成树 5.下列算法中通常以自底向上的方式求解最优解的是( B )。 A、备忘录法 B、动态规划法 C、贪心法 D、回溯法 6、衡量一个算法好坏的标准是( C )。 A 运行速度快 B 占用空间少 C 时间复杂度低 D 代码短 7、以下不可以使用分治法求解的是( D )。 A 棋盘覆盖问题 B 选择问题 C 归并排序 D 0/1背包问题 8. 实现循环赛日程表利用的算法是( A )。 A、分治策略 B、动态规划法 C、贪心法 D、回溯法 9.下面不是分支界限法搜索方式的是( D )。 A、广度优先 B、最小耗费优先 C、最大效益优先 D、深度优先 10.下列算法中通常以深度优先方式系统搜索问题解的是( D )。 A、备忘录法 B、动态规划法 C、贪心法 D、回溯法 11.备忘录方法是那种算法的变形。( B ) A、分治法 B、动态规划法 C、贪心法 D、回溯法 12.哈夫曼编码的贪心算法所需的计算时间为( B )。 A、O(n2n) B、O(nlogn) C、O(2n) D、O(n) 13.分支限界法解最大团问题时,活结点表的组织形式是( B )。 A、最小堆 B、最大堆 C、栈 D、数组 14.最长公共子序列算法利用的算法是( B )。 A、分支界限法 B、动态规划法 C、贪心法 D、回溯法 15.实现棋盘覆盖算法利用的算法是( A )。 A、分治法 B、动态规划法 C、贪心法 D、回溯法 16.下面是贪心算法的基本要素的是( C )。 A、重叠子问题 B、构造最优解 C、贪心选择性质 D、定义最优解 17.回溯法的效率不依赖于下列哪些因素( D ) A.满足显约束的值的个数 B. 计算约束函数的时间 C.计算限界函数的时间 D. 确定解空间的时间 18.下面哪种函数是回溯法中为避免无效搜索采取的策略( B ) A.递归函数 B.剪枝函数 C。随机数函数 D.搜索函数 19. ( D )是贪心算法与动态规划算法的共同点。

分治算法实验

中南大学 《算法设计与分析》实验报告 姓名: 专业班级: 学号: 指导教师: 完成日期:2010.1

一.实验名称 分治算法实验 二.实验目的 1. 了解分治策略算法思想 2. 掌握快速排序、归并排序算法 3. 了解其他分治问题典型算法 三.实验内容 1. 编写一个简单的程序,实现归并排序。 2. 编写一段程序,实现快速排序。 3. 编写程序实现循环赛日程表。设有n=2k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其它n-1个选手各赛一次(2)每个选手一天只能赛一场(3)循环赛进行n-1天 四.算法思想分析 1. 归并排序 归并排序算法思想: 分而治之(divide - conquer),即每个递归过程涉及三个步骤:第一, 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括n/2 个元素。第二, 治理: 对每个子序列分别调用归并排序MergeSort,进行递归操作。第三, 合并: 合并两个排好序的子序列,生成排序结果。 归并操作的工作原理如下: (1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 (2)设定两个指针,最初位置分别为两个已经排序序列的起始位置 (3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 (4)重复步骤3直到某一指针达到序列尾 (5)将另一序列剩下的所有元素直接复制到合并序列尾 比较操作的次数介于(nlogn) / 2和nlogn ? n + 1。赋值操作的次数是(2nlogn)。归并算法的空间复杂度为:Θ (n)

2. 快速排序 快速排序法的基本精神是在数列中找出适当的轴心,然后将数列一分为二,分别对左边与右边数列进行排序,而影响快速排序法效率的正是轴心的选择。 (1)分解:将输入的序列L[p..r]划分成两个非空子序列L[p..q]和L[q+1..r],使L[p..q]中任一元素的值不大于L[q+1..r]中任一元素的值。 (2)递归求解:通过递归调用快速排序算法分别对L[p..q]和L[q+1..r]进行排序。 (3)合并:由于对分解出的两个子序列的排序是就地进行的,所以在L[p..q]和L[q+1..r]都排好序后不需要执行任何计算L[p..r]就已排好序。 3. 循环赛日程表 按分治策略,将所有的选手分为两组,n个选手的比赛日程表就可以通过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割,直到只剩下2个选手时,比赛日程表的制定就可以简单的处理了。 五.算法源代码及用户屏幕 1.归并排序 (备注:语言C++;编译器:MS VS2008;共2个文件) head.h文件 #include #include using namespace std; void mergeSort(int *a,int left,int right); void merge(int *a,int left,int i,int right); main.cpp文件 #include "head.h" void main() { int test[]={0,12,45,3,6,29,4,16,77}; cout<<"before:"; for(int i=0;i<=8;i++) { cout<

相关文档
最新文档