减治法

第5章减治法(Decrease and Conquer)

减治法的基本思想

规模为n的原问题的解与较小规模(通常是n/2)的子问题的解之间具有关系:

(1)原问题的解只存在于其中一个较小规模的子

问题中;

(2)原问题的解与其中一个较小规模的解之间存

在某种对应关系。

由于原问题的解与较小规模的子问题的解之

间存在这种关系,所以,只需求解其中一个

较小规模的子问题就可以得到原问题的解。

2

减治法的基本思想

一旦建立了这种关系,

就可以从顶至下(递归),

也可以从底至上(非递归)的来运用

Example, n!

A top down (recursive) solution

A bottom up (iterative) solution

3

减治法的类型

减治法有三种变种:

1)减去一个常量

2)减去一个常数因子

3)减去的规模是可变的gcd(m, n)4

减(一)治技术

a problem of size n

subproblem

of size n-1

a solution to the

subproblem

e.g., n!

a solution to

the original problem

5

减(半) 治技术

a problem of size n

subproblem

of size n/2

a solution to the

subproblem

e.g., Binary search

a solution to

the original problem

6

7

典型的分治法

subproblem 2 of size n /2

subproblem 1

of size n /2a solution to

subproblem 1 a solution to

the original problem

a solution to subproblem 2

a problem of size n

e.g., mergesort

减治与分治的区别

考虑以下指数问题: 计算a n

减一法

Bottom-up: iterative (brute Force) Top-down:recursive

分治法:

减常因子法:a n= a*a*a*a*...*a

a n= a n-1* a if n > 1

= a if n = 1

a n= a ?n/2 ?* a ?n/2?if n > 1

= a if n = 1

a n = (a n/2 ) 2if n is even and positive

= (a(n-1)/2 ) 2 * a if n is odd and > 1 = a if n = 1

O (log

2

n) O (n log

2

n)

8

9

1

11)2/(0)(>=???+=n n n T n T 所以,通常来说,应用减治法处理问题的效率是很高的,一般是O (log 2n

)数量级。

减治法只对一个子问题求解,并且不需要进行解的合并。应用减治法(例如减半法)得到的算法通常具有如下递推式:

5.1 插入排序Play card

如何排序手中的扑克牌?

10

算法示例

11

插入排序: 迭代实现

算法InsertionSortIter(A[0..n-1])

//An iterative implementation of insertion sort

//Input: An array A[0..n-1] of n orderable elements

//Output: Array A[0..n-1] sorted in nondecreasing order

for i ?1 to n –1 do// i: the index of the first element of the unsorted part.

key = A[i]

for j ?i –1 to 0 do// j: the index of the sorted part of the array if (key< A[j])//compare the key with each element in the sorted part A[j+1] ?A[j]

A[j +1] ?key//insert the key to the sorted part of the array

算法是否正确?

12

插入排序:递归实现ALGORITHM InsertionSortRecur(A[0..n-1], n-1)

//A recursive implementation of insertion sort

//Input: An array A[0..n-1] of n orderable elements

//Output: Array A[0..n-1] sorted in nondecreasing order

if n > 1

InsertionSortRecur(A[0..n-2], n-2)

Insert(A[0..n-2], n-1) //insert A[n-1] to A[0..n-2]

ALGORITHM Insert(A[0..m-1], m)

//Insert A[m] to the sorted subarray A[0..m-1] of A[0..n-1]

//Input: A subarray A[0..m] of A[0..n-1]

//Output: Array A[0..m] sorted in nondecreasing order

key = A[m]

for j ?m –1 to 0 do

if (key< A[j])

A[j+1] ?A[j]

else

break A[j +1] ?key 有问题么?

Index of the element/key to be inserted.

Index of the last element

13

算法效率分析

14

图的遍历Graph Traversal

许多实际问题要求系统的处理图的所有顶点和边

G = < V , E >

图的遍历算法:

深度优先查找Depth-first search

广度优先查找Breadth-first search

15

5.2.1 深度优先查找

基本思想

traverse “deeper”whenever possible.

将当前顶点标记为已访问。

每次迭代,算法处理与当前顶点邻接的未访问顶点,如果存在多个邻居,则根据顶点的字母顺序来选择顶点。

当到达一个死端(一个顶点的所有邻接顶点都已经被访问),算法沿来路后退一步(一条边),并尝试继续从该处访问未访问的顶点,当算法后退到起始顶点,且起始顶点也为死端时,算法终止。

与树的前序遍历很相似

用栈来跟踪深度查找的操作比较方便.

第一次访问一个顶点时将其入栈.

当顶点成为死端的时候出栈

16

17

Example –无向图

深度遍历:

给出顶点的访问(入栈)顺序和出栈顺序.a b e f c d g h order pushed onto stack: a b f e g c d h

order popped from stack: e f h d c g b a

18

深度优先查找(DFS)Pseudocode for Depth-first-search of graph G=(V,E)dfs(v )//Use depth-first to visit a connected component starting //from vertex v.count ?count + 1

mark v with count //visit vertex v

for each vertex w adjacent to v do if w is marked with 0 //w has not been visited yet .dfs(w)

DFS(G) // Use depth-first to visit a graph, which might // contain multiple connected components.

count ?0 //visiting sequence number

mark each vertex with 0 // (unvisited)

for each vertex v ∈V do

if v is marked with 0 //w has not been visited yet.

dfs(v)

19

5.2.2 广度优先查找(BFS)

Prim’s最小生成树算法的原型Archetype

Dijkstra’s最短路径算法原型

基本思想

Traverse “wider”whenever possible.

将当前顶点标记为已访问

访问当前顶点的所有邻接顶点

在访问k+1层的任一顶点之前访问k层的所有顶点

类似树的逐层遍历

BFS采用队列来跟踪操作

20

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="<

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

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

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

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

分治算法实验

中南大学 《算法设计与分析》实验报告 姓名: 专业班级: 学号: 指导教师: 完成日期: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<

分治法实现快速排序

实验一 实验名称:利用分治法实现快速排序实验时间: 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(int a[],int p,int r)

{ if(px); if(i>=j) break;

最近点对分治法

假设在一片金属上钻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/92935660.html,/p-198711591.html?qq-pf-to=pcqq.c2c 代码如下: #include #include #include

二分搜索算法和快速排序算法及分治策略

实验课程:算法分析与设计 实验名称:实验二C/C++环境及递归算法(综合性/设计性) 实验目标: 1、熟悉二分搜索算法和快速排序算法; 2、初步掌握分治算法; 实验任务: 掌握分治策略的概念和基本思想。 实验题: 1、设a[0:n-1]是一个已排好序的数组。请改写二分搜索算法,使得当搜索元素x不在数组中时,返回小于x的最大元素的位置i和大于x的最小元素位置j。当搜索元素在数组中时,I 和j相同,均为x在数组中的位置。设有n个不同的整数排好序后存放于t[0:n-1]中,若存在一个下标i,0≤i<n,使得t[i]=i,设计一个有效的算法找到这个下标。要求算法在最坏的情况下的计算时间为O(logn)。 2、在快速排序中,记录的比较和交换是从两端向中间进行的,关键字较大的记录一次就能交换到后面单元,关键字较小的记录一次就能交换到前面单元,记录每次移动的距离较大,因而总的比较和移动次数较少。 实验设备及环境: PC;C/C++的编程环境Visual C++。 实验主要步骤: (1)明确实验目标和具体任务; (2)理解实验所涉及的分治算法; (3)编写程序并实现分治算法; (4)设计实验数据并运行程序、记录运行的结果; 实验数据及运行结果、实验结果分析及结论: 1、#include using namespace std; int main() { int const length=100; int n,x; int a[length]; cout<<"依次输入数组的长度,数组内容,要查找的数"<>n; //输入数组的长度 for(int i=0;i>a[i]; cin>>x;

算法分析复习题(含答案)

一、选择题 1、衡量一个算法好坏的标准是( C )。 (A)运行速度快(B)占用空间少(C)时间复杂度低(D)代码短 2、记号O的定义正确的是(A)。 (A)O(g(n)) = { f(n) | 存在正常数c和n0使得对所有n≥n0有:0≤ f(n) ≤ cg(n) };(B)O(g(n)) = { f(n) | 存在正常数c和n0使得对所有n≥n0有:0≤ cg(n) ≤ f(n) };(C)O(g(n)) = { f(n) | 对于任何正常数c>0,存在正数和n0 >0使得对所有n≥n0 有:0 ≤f(n)0,存在正数和n0 >0使得对所有n≥n0 有:0 ≤cg(n) < f(n) }; 3、二分搜索算法是利用( A )实现的算法。 (A)分治策略(B)动态规划法(C)贪心法(D)回溯法 4、使用分治法求解不需要满足的条件是(A )。 (A)子问题必须是一样的(B)子问题不能够重复 (C)子问题的解可以合并(D)原问题和子问题使用相同的方法解 5、合并排序算法是利用( A )实现的算法。 (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、实现棋盘覆盖算法利用的算法是( A )。 (A)分治法(B)动态规划法(C)贪心法(D)回溯法 10、矩阵连乘问题的算法可由( B)设计实现。 (A)分支界限算法(B)动态规划算法(C)贪心算法(D)回溯算法 11、实现大整数的乘法是利用的算法( C )。 (A)贪心法(B)动态规划法(C)分治策略(D)回溯法 12、最长公共子序列算法利用的算法是( B )。 (A)分支界限法(B)动态规划法(C )贪心法(D)回溯法 13、下列算法中通常以自底向上的方式求解最优解的是( B )。 (A)备忘录法(B)动态规划法(C)贪心法(D)回溯法 14、下列是动态规划算法基本要素的是( D )。 (A)定义最优解(B)构造最优解(C)算出最优解(D)子问题重叠性质15、下列不是动态规划算法基本步骤的是( A )。 (A)找出最优解的解空间(B)构造最优解(C)算出最优解(D)定义最优解 16、能采用贪心算法求最优解的问题,一般具有的重要性质为:( A ) (A)最优子结构性质与贪心选择性质(B)重叠子问题性质与贪心选择性质 (C)最优子结构性质与重叠子问题性质(D)预排序与递归调用 17、下面问题(B )不能使用贪心法解决。 (A)单源最短路径问题(B)N皇后问题 (C)最小花费生成树问题(D)背包问题 18、以下不可以使用分治法求解的是(D )。 (A)棋盘覆盖问题(B)选择问题(C)归并排序(D)0/1背包问题

分治算法

《算法设计与分析》实验报告 实验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++];

算法分析与设计部分含计算的复习题及参考答案

二、简答题: 1.备忘录方法和动态规划算法相比有何异同?简述之。 2.简述回溯法解题的主要步骤。 3.简述动态规划算法求解的基本要素。 4.简述回溯法的基本思想。 5.简要分析在递归算法中消除递归调用,将递归算法转化为非递归算法的方法。 6.简要分析分支限界法与回溯法的异同。 7.简述算法复杂性的概念,算法复杂性度量主要指哪两个方面? 8.贪心算法求解的问题主要具有哪些性质?简述之。 9.分治法的基本思想是什么?合并排序的基本思想是什么?请分别简述之。 10.简述分析贪心算法与动态规划算法的异同。 三、算法编写及算法应用分析题: 1.已知有3个物品:(w1,w2,w3)=(12,10,6),(p1,p2,p3)=(15,13,10),背包的容积M=20,根据0-1背包动态规划的递推式求出最优解。 2.按要求完成以下关于排序和查找的问题。 ①对数组A={15,29,135,18,32,1,27,25,5},用快速排序方法将其排成递减序。 ②请描述递减数组进行二分搜索的基本思想,并给出非递归算法。 ③给出上述算法的递归算法。 ④使用上述算法对①所得到的结果搜索如下元素,并给出搜索过程:18,31,135。 3.已知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=12,r 5=5,r 6=50,r 7=6, 求矩阵链积A 1×A 2×A 3×A 4×A 5×A 6的最佳求积顺序(要求给出计算步骤)。 4.根据分枝限界算法基本过程,求解0-1背包问题。 已知n=3,M=20,(w1,w2,w3)=(12,10,6),(p1,p2,p3)=(15,13,10)。 5.试用贪心算法求解汽车加油问题:已知一辆汽车加满油后可行驶n 公里,而旅途中有若干个加油站。试设计一个有效算法,指出应在哪些加油站停靠加油,使加油次数最少,请写出该算法。 6.试用动态规划算法实现下列问题:设A 和B 是两个字符串。我们要用最少的字符操作,将字符串A 转换为字符串B ,这里所说的字符操作包括: ①删除一个字符。 ②插入一个字符。 ③将一个字符改为另一个字符。 请写出该算法。 7.对于下图使用Dijkstra 算法求由顶点a 到顶点h 的最短路径。 8.试写出用分治法对数组A[n]实现快速排序的算法。 9.有n 个活动争用一个活动室。已知活动i 占用的时间区域为[s i ,f i ],活动i,j 相容的条件是:sj ≥f i ,问题的解表示为(x i | x i =1,2…,n,),x i 表示顺序为i 的活动编号活动,求一个相容的活动子集,且安排的活动数目最多。 10.设x 1、x 2、x 3是一个三角形的三条边,而且x 1+x 2+x 3=14。请问有多少种不同的三角形?给出解答过程。 11.设数组A 有n 个元素,需要找出其中的最大最小值。 ①请给出一个解决方法,并分析其复杂性。 ②把n 个元素等分为两组A1和A2,分别求这两组的最大值和最小值,然后分别将这两组的最大值和最

分治算法(实现求最大最小值和快速排序)

实验一分治算法 一、实验目的 1)掌握分治算法的设计思想与分析方法, 2)能够按题目要求编程实现分治算法。 二、方法原理 将一个规模为n的原问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同;递归地求解这些子问题,然后将子问题的解合并为原问题的解。 三、实验设备 PC机一台,C语言、PASCAL语言、Matlab任选 四、掌握要点 将原问题分解为若干规模较小、互相独立、与原问题形式相同的子问题;求解子问题;将子问题的解合并为原问题的解。 五、实验内容 1)采用分治算法求10个实数{ 9,3,6,2,1,8,4,5,7,23 }序列中的最大元素和最小元素,并分析算法的时间复 杂度。 2)编程实现:采用分治算法方法实现快速排序算法。要求:输入数组为{9,4,6,2,5,8,4,5,6,22 };限定数组 排序范围;输出显示为递增顺序排序的数组。 六、实验要求 1)认真分析题目的条件和要求,复习相关的理论知识,选择适当的解决方案和算法; 2)编写上机实验程序,作好上机前的准备工作; 3)上机调试程序,并试算各种方案,记录计算的结果(包括必要的中间结果); 4)分析和解释计算结果; 5)按照要求书写实验报告; 源代码: 1.分治算法求10个实数{ 9,3,6,2,1,8,4,5,7,23 }序列中的最大元素和最小元素 #include #include int* getmaxmin(int a, int b) { int* t = new int[2];//动态 if (a < b) { t[0] = a; t[1] = b; }

算法分析——分治法

分治算法 小组的汇报内容: 一、分治算法的基本概念 (2) 二、分治算法的基本思想及策略 (2) 三、分治法适用的情况 (3) 四、分治法的基本步骤 (3) 五、分治法的复杂性分析 (4) 六、快速傅里叶变换 (5) 七、可使用分治法求解的一些经典问题 (9) 八、依据分治法设计程序时的思维过程 (9) 九、分治法与其它常见算法的比较 (9) 小组的分工情况: 彭勇讲前五个部分,天西山讲第六个部分,胡化腾讲最后三个部分,吕璐负责汇报的资料收集,小组分工以及最后的资料整理。

三、分治法适用的情况 分治法所能解决的问题一般具有以下几个特征: 1) 该问题的规模缩小到一定的程度就可以容易地解决 2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。 3) 利用该问题分解出的子问题的解可以合并为该问题的解; 4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。 第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加; 第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;、 第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。 第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。 四、分治法的基本步骤 分治法在每一层递归上都有三个步骤: step1 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题; step2 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题

分治法实验报告

算法实验报告一分治法实验 一、实验目的及要求 利用分治方法设计大整数乘法的递归算法,掌握分治法的基本思想和算法设计的基本步 骤。 要求:设计十进制的大整数乘法,必须利用分治的思想编写算法,利用c语言(或者c++ 语言)实现算法,给出程序的正确运行结果。(必须完成) 设计二进制的大整数乘法,要求利用分治的思想编写递归算法,并可以实现多位数的乘 法(利用数组实现),给出程序的正确运行结果。(任选) 二、算法描述 1、 输入两个相同位数的大整数u,v 输出uv的值 判断大整数的位数i; w=u/10^(i/2); y=v/10^(i/2); x=u-w*10^(i/2); z= v-y*10^(i/2); 然后将w,x,y,z代入公式求得最后结果 uv=wy10^i+((w+x)(y+z)-wy-xz)10^(i/2)+xz 三、调试过程及运行结果 在实验中我遇到的问题: 原来以为这两个大整数的位数不同,结果题目要求是相同位数的大整数在写10的多少 次方时,写的是10^(i/2),10^(i),结果不对,我就将它改成了for循环语句 四、实验总结 在本次实验中,我知道了分治算法,以及分治算法的基本思想。我还掌握了编写大整数 乘法的算法与步骤,以及如何修改在编写程序时遇到的问题。 五、附录(源程序代码清单) 1、#include<iostream.h> int weishu(int x) { int i; while(x!=0) { x=x/10; i++; } return i; } void main() { int u,v; cout<<输入两个位数相同的大整数:<<endl; cin>>u; cin>>v;

相关文档
最新文档