实验一 分治法合并排序
分治算法实验报告(C语言)

实验1、《分治算法实验》一、实验目的1. 了解分治策略算法思想2. 掌握快速排序、归并排序算法3. 了解其他分治问题典型算法二、实验内容1.编写一个简单的程序,实现归并排序。
2. 编写一段程序,实现快速排序。
3. 编写程序实现循环赛日程表。
设有n=2k个运动员要进行网球循环赛。
现要设计一个满足以下要求的比赛日程表:(1)每个选手必须与其它n-1个选手各赛一次(2)每个选手一天只能赛一场(3)循环赛进行n-1天三、算法思想分析1.归并排序先是将待排序集合分成两个大小大致相同的集合,分别对每个集合进行排序,递归调用归并排序函数,再是调用合并函数,将两个集合归并为一个排好序的集合。
2.快速排序先是选择关键数据作为比较量,然后将数组中比它小的数都放到它的左边,比它大的数放大右边,再对左右区间重复上一步,直至各个区间只有一个数。
3.循环赛日程表先将选手分为两部分,分别排序,再将两部分合并,合并时由于循环赛的规律得知直接将左上角的排序表复制到右下角,左下角的排序表复制到右上角即可。
分成两部分时需要利用递归不断分下去直至只剩下一位选手。
四、实验过程分析1.通过归并算法我对分治算法有了初步的实际操作经验,快速排序与归并算法有很大的相似点,但是在合并时的方法不一样,而循环赛日程表则是思路问题,这个题目编程难点应该在于合并时数组调用的for循环的次数以及起始位置问题。
2.对于分治算法一般是将大规模问题分解为小问题,通过递归不断分下去,然后对每个小规模用一个函数去求解。
适用于小规模独立且易解,可以合并到大问题具有最优子结构的问题。
3.归并排序和快速排序熟悉书本及PPT基本没有问题,循环赛日程表则是纠结了很久,一开始算法思路并不是十分清晰所以错了很多次,后来想了很久再观察PPT的循环赛日程表得知最终算法,编写代码中遇到了一个小问题,有一部分选手未排序,如图所示:图中有部分选手未排序,即左下角排序出现了问题,后来直接静态调试,自己按照代码用实际数据去试了一遍,发现是排序时的for循环的次数不对。
分治法-合并排序和快速排序

分治法-合并排序和快速排序分治法是按照以下⽅案⼯作的:将问题的实例划分为同⼀个问题的⼏个较⼩的实例,最好拥有同样的规模对这些较⼩的实例求解(⼀般使⽤递归⽅法,但在问题规模⾜够⼩的时候,有时会利⽤另⼀种算法以提⾼效率)如果必要的话,合并较⼩问题的解,以得到原始问题的解分治法的流程:4.1 合并排序合并排序是成功应⽤分治技术的⼀个完美例⼦(书上说的)。
对于⼀个需要排序的数组,合并排序把它⼀分为⼆,并对每个⼦数组递归排序,然后把这两个排好序的⼦数组合并为⼀个有序数组。
代码实现:/*** 合并排序* @author xiaofeig* @since 2015.9.16* @param array 要排序的数组* @return返回排好序的数组* */public static int[] mergeSort(int[] array){if(array.length>1){int[] subArray1=subArray(array,0,array.length/2);int[] subArray2=subArray(array,array.length/2,array.length);subArray1=mergeSort(subArray1);subArray2=mergeSort(subArray2);return merge(subArray1,subArray2);}return array;}/*** 返回指定数组的⼦数组* @author xiaofeig* @since 2015.9.16* @param array 指定的数组* @param beginIndex ⼦数组的开始下标* @param endIndex ⼦数组的结束位置(不包括该元素)* @return返回⼦数组* */public static int[] subArray(int[] array,int beginIndex,int endIndex){int[] result=new int[endIndex-beginIndex];for(int i=beginIndex;i<endIndex;i++){result[i-beginIndex]=array[i];}return result;}/*** 根据数值⼤⼩合并两个数组* @author xiaofeig* @since 2015.9.16* @param subArray1 待合并的数组* @param subArray2 待合并的数组* @return返回合并好的数组* */public static int[] merge(int[] subArray1,int[] subArray2){int[] result=new int[subArray1.length+subArray2.length];int i=0,j=0;while(i<subArray1.length&&j<subArray2.length){if(subArray1[i]>subArray2[j]){result[i+j]=subArray2[j];j++;}else{result[i+j]=subArray1[i];i++;}}if(i==subArray1.length){while(j<subArray2.length){result[i+j]=subArray2[j];}}else{while(i<subArray1.length){result[i+j]=subArray1[i];i++;}}return result;}算法分析:当n>1时,C(n)=2C(n-2)+C merge(n),C(1)=0C merge(n)表⽰合并阶段进⾏键值⽐较的次数。
分治算法的实验报告

一、实验背景分治算法是一种常用的算法设计方法,其基本思想是将一个复杂问题分解成若干个相互独立的小问题,然后将小问题递归求解,最终将子问题的解合并为原问题的解。
分治算法具有高效性、可扩展性和易于实现等优点,被广泛应用于各个领域。
本实验旨在通过实现分治算法解决实际问题,掌握分治算法的设计思想,并分析其时间复杂度。
二、实验目的1. 理解分治算法的基本思想;2. 掌握分治算法的递归实现方法;3. 分析分治算法的时间复杂度;4. 应用分治算法解决实际问题。
三、实验内容本实验选择两个分治算法:快速排序和合并排序。
1. 快速排序快速排序是一种高效的排序算法,其基本思想是将待排序序列分为两个子序列,其中一个子序列的所有元素均小于另一个子序列的所有元素,然后递归地对两个子序列进行快速排序。
(1)算法描述:① 选择一个基准值(pivot),通常取序列的第一个元素;② 将序列分为两个子序列,一个子序列包含所有小于基准值的元素,另一个子序列包含所有大于基准值的元素;③ 递归地对两个子序列进行快速排序。
(2)代码实现:```cvoid quickSort(int arr[], int left, int right) {if (left < right) {int pivot = arr[left];int i = left;int j = right;while (i < j) {while (i < j && arr[j] >= pivot) {j--;}arr[i] = arr[j];while (i < j && arr[i] <= pivot) {i++;}arr[j] = arr[i];}arr[i] = pivot;quickSort(arr, left, i - 1);quickSort(arr, i + 1, right);}}```2. 合并排序合并排序是一种稳定的排序算法,其基本思想是将待排序序列分为两个子序列,分别对两个子序列进行排序,然后将排序后的子序列合并为一个有序序列。
实验1归并排序分治策略的设计与实现

实验1归并排序分治策略的设计与实现实验1 归并排序分治策略的设计与实现一、实验目的1、熟悉分治法求解问题的抽象控制策略;2、熟悉在顺序存储表示下求解分类问题的递归算法设计;3、通过实例转换, 掌握分治法应用。
二、实验内容1、学习分治方法的原理;2、针对分治问题设计递归算法实现归并排序算法;3、根据归并排序的递归算法改写成迭代算法。
4、测试程序与验收并进一步将程序改写成模块化可用程序。
三、实验程序的功能模块【模块】void Merge(int r[],int r1[],int s,int m,int t){ 实现数组中的已分好类的两部分进行合并 }void MergeSort(int r[],int r1[],int s,int t){ 对数组中从下标low开始到heigh结束的部分进行分类 }【递归实现】//合并数组void Merge(int r[],int r1[],int s,int m,int t)// r[]为待排序数列 r1[]用来存放排好序的数列三个int型变量 s m t ,分别为数组的最左,中间,最右{int i=s;int j=m+1;int k=s;while(i<=m && j<=t){if(r[i]<=r[j]) //左右两边的数组从头开始比,选择小者放入r1r1[k++]=r[i++];else r1[k++]=r[j++];}if(i<=m) //若比完之后,左边有剩下,依次填入r1while(i<=m)r1[k++]=r[i++];else //比完之后,右边有剩下,依次填入r1while(j<=t)r1[k++]=r[j++];for(int l=0;l<="">r[l]=r1[l];}//归并算法void MergeSort(int r[],int r1[],int s,int t){//结束归并条件,数组内只有一个元素if(s==t)r1[s]=r[s];else{int m=(s+t)/2; //规定变量m,数组中间MergeSort(r,r1,s,m); //左边归并MergeSort(r,r1,m+1,t); //右边归并Merge(r1,r,s,m,t); //合并}}【迭代实现】//合并算法sort为合并后数组,list为待合并数组,low,center,high分别为待合并数组的最左边,中间,最右边void merge(int *sort, int *list, int low, int center, int high)int i,j,k;//i,j分别代表两个小数组的最左边,通过比较,选择小者放入合并后数组for(i=low,j=(center+1),k=low; i<=center && j<=high;++k) {if(list[i] > list[j]) //若左边数组大,放右边数组未用的最左边的元素进sortsort[k] = list[j++];elsesort[k] = list[i++];}while(i<=center) //若左边数组还有元素,依次填入sortsort[k++] = list[i++];while(j<=high) //若右边数组还有元素,依次填入sortsort[k++] = list[j++];}//每次步长分组a是分组后数组,b是待分组数组,length为步长(小组长度),n为大数组总长void merge_pass(int *a, int *b, int length, int n){int i;//从数组最左边开始,按照步长分组,直到不够元素达到步长可以分组(剩最后一组)for(i=0; i<=n-2*length; i+=2*length) {int center = (i + i + 2*length - 1)/2; //定义每个小组的中间merge(a, b, i, center, i+2*length-1); //每个小组调用合并算法,最左边就是i,最右边是i+2*length-1}if((i+length)<="">int center = (i + i + 2*length - 1)/2; //定义此小组的中间merge(a, b, i, center, n-1); //调用合并算法,最右边是n-1}else //最后一个分组不够元素达到步长,复制{while(i<="" a[i]="b[i];" p="" {="">}}}//归并算法 array 为待排序数组,n为数组长度void m_sort(int *array, int n){int extra[30];int length = 1;while(length < n) //以步长为分的标准{//分组归并,结果放到extramerge_pass(extra, array, length, n);//步长增长为两倍length *= 2;//再次分组归并,结果放回arraymerge_pass(array, extra, length, n);length *= 2;}}四、递归算法改写成迭代算法的一般方法1、递归一般分为三部分,开始状态,一般状态,结束状态。
分治算法的技巧

分治算法的技巧分治算法是一种常用的问题求解方法,它将复杂的问题分解成多个相同或相似的子问题,然后分别求解这些子问题,最后将子问题的解合并得到原问题的解。
在实际应用中,分治算法有一些常用的技巧可以优化解决问题的效率。
一、合并排序合并排序是分治算法的典型应用之一,它的核心思想是将待排序的数组分成两个大致相等的子数组,分别对这两个子数组进行排序,然后再将排序后的子数组合并成一个有序的数组。
在合并的过程中,有一种非常高效的方法,即“双指针法”。
该方法的基本思想是设置两个指针,分别指向待合并的两个有序数组的起始位置,然后比较两个指针所指的元素大小,将较小的元素放入新数组中,同时对应指针向后移动一位。
重复这个过程,直到其中一个指针越界,然后将另一个有序数组中剩余的元素全部放到新数组的末尾。
这种“双指针法”可以在O(n)的时间复杂度内完成合并排序的操作,因此在实际应用中非常高效。
二、快速排序快速排序是另一个典型的分治算法应用,它的基本思想是选择一个元素作为基准,将数组中比基准小的元素放在基准的左边,比基准大的元素放在基准的右边,然后对基准的左右两个子数组进行递归排序。
在快速排序的实现过程中,有一种重要的技巧叫做“分区操作”。
该操作的基本思想是通过一个游标将数组划分为两个区域,左侧的区域元素都小于等于基准,右侧的区域元素都大于等于基准。
具体实现时,可以选择数组中的第一个元素作为基准,然后设置两个指针,一个指向数组的起始位置,一个指向数组的末尾位置。
然后不断移动指针,直到左右指针相遇,将当前的元素与基准进行比较,如果小于基准,则将该元素与左侧区域的下一个位置进行交换,同时左指针向后移动一位;如果大于基准,则将该元素与右侧区域的前一个位置进行交换,同时右指针向前移动一位。
重复这个过程,直到左右指针相遇,将基准元素与指针所指的元素进行交换,这样基准就找到了最终的位置。
分区操作是快速排序算法的核心,通过合理的设计和实现可以提高算法的效率。
算法分析与设计实验报告合并排序快速排序

算法分析与设计实验报告:合并排序与快速排序一、引言算法是计算机科学中非常重要的一部分,它涉及到解决问题的方法和步骤。
合并排序和快速排序是两种经典而常用的排序算法。
本文将对这两种排序算法进行分析和设计实验,通过对比它们的性能和效率,以期得出最优算法。
二、合并排序合并排序是一种分治算法,它将原始数组不断分解为更小的数组,直到最后细分为单个元素。
然后,再将这些单个元素两两合并,形成一个有序数组。
合并排序的核心操作是合并两个有序的数组。
1. 算法步骤(1)将原始数组分解为更小的子数组,直到每个子数组只有一个元素;(2)两两合并相邻的子数组,同时进行排序,生成新的有序数组;(3)重复步骤(2),直到生成最终的有序数组。
2. 算法性能合并排序的最优时间复杂度为O(nlogn),其中n为待排序数组的长度。
无论最好情况还是最坏情况,合并排序的复杂度都相同。
合并排序需要额外的存储空间来存储临时数组,所以空间复杂度为O(n)。
三、快速排序快速排序也是一种分治算法,它将原始数组根据一个主元(pivot)分成两个子数组,一个子数组的元素都小于主元,另一个子数组的元素都大于主元。
然后,递归地对这两个子数组进行排序,最后得到有序数组。
快速排序的核心操作是划分。
1. 算法步骤(1)选择一个主元(pivot),可以是随机选择或者固定选择第一个元素;(2)将原始数组根据主元划分为两个子数组,一个子数组的元素都小于主元,另一个子数组的元素都大于主元;(3)递归地对这两个子数组进行快速排序;(4)重复步骤(2)和(3),直到每个子数组只有一个元素,即得到最终的有序数组。
2. 算法性能快速排序的平均时间复杂度为O(nlogn),其中n为待排序数组的长度。
最坏情况下,当每次选择的主元都是最小或最大元素时,时间复杂度为O(n^2)。
快速排序是原地排序,不需要额外的存储空间,所以空间复杂度为O(1)。
四、实验设计为了验证合并排序和快速排序的性能和效率,我们设计以下实验:1. 实验目的:比较合并排序和快速排序的时间复杂度和空间复杂度。
分治法实现归并排序算法算法设计与分析实验报告(word文档良心出品)

算法设计与分析实验报告实验名称分治法实现归并排序算法评分实验日期年月日指导教师姓名专业班级学号一.实验要求1.了解用分治法求解的问题:当要求解一个输入规模为n,且n的取值相当大的问题时,如果问题可以分成k个不同子集合,得到k个不同的可独立求解的子问题,其中1<k≤n,而且子问题与原问题性质相同,原问题的解可由这些子问题的解合并得出。
那末,对于这类问题分治法是十分有效的。
2.掌握分治法的一般控制流程。
DanC(p,q)global n,A[1:n]; integer m,p,q; // 1≤p≤q≤nif Small(p,q) then return G(p,q);else m=Divide(p,q); // p≤m<qreturn Combine(DanC(p,m),DanC(m+1,q));endifend DanC3.实现典型的分治算法的编程与上机实验,验证算法的时间复杂性函数。
二.实验内容1.编程实现归并排序算法,程序中加入比较次数的计数功能,输出排序结果和比较次数。
2.输入10组相同的数据,验证排序结果和完成排序的比较次数。
3.与复杂性函数所计算的比较次数比较。
4.用表格列出比较结果。
5.给出文字分析。
三.程序算法1. 归并排序算法procedure MERGESORT(low,high)//A(low;high)是一个全程数组,它含有high-low+1≥0个待排序的元素//integer low,high;if low<high;then mid←, //求这个集合的分割点//call MERGESORT(low,mid) //将一个子集合排序//call MERGESORT(mid+1,high) //将另一个子集合排序call MERGE(low,mid,high) //归并两个已排序的子集合// endifend MERGESORT归并两个已排序的集合procedure MERGE(low,mid,high)//A(low:high)是一个全程数组////辅助数组B(low;high)//integer h,i,j,k;h←low;i←low;j←mid+1;while h≤mid and j≤high do //当两个集合都没取尽时// if A(h)≤A(j) then B(i) ←A(h);h←h+1else B(i) ←A(j);j←j+1endifi←i+1repeatif h>mid thenfor k←j to high do //处理剩余的元素//B(i) ←A(k);i←i+1repeatelse for k←h to mid doB(i) ←A(k);i←i+1repeatendif将已归并的集合复制到Aend MERGE2. 快速排序算法QuickSort(p,q)//将数组A[1:n]中的元素A[p], A[p+1], , A[q]按不降次序排列,并假定A[n+1]是一个确定的、且大于A[1:n]中所有的数。
分治法实现一组无序序列的两路合并排序和快速排序

void SortableList::Input(){
for(int i=0;i<maxSize;i++){
cin>>l[i];
n++;
}
}
void SortableList::Output(){
for(int i=0;i<maxSize;i++){
cout<<l[i]<<" ";
cout<<endl;
void Input();
void Output();
private:
int *l;
int maxSize;
int n;
void MergeSort(int left,int right);
void Merge(int left,int mid,int right);
};
void SortableList::MergeSort(){
cout<<"请输入10个数:"<<endl;
l.Input();
l.MergeSort();
l.Oห้องสมุดไป่ตู้tput();
}
(二)快速排序
#include<iostream.h>
class SortableList
{
public:
SortableList(int mSize){
maxSize=mSize;
2、如果采用顺序存储的可排序表作为算法实现的数据结构,则需要定义一个可排序表类SortableList,两路合并算法和快速排序算法均由定义在该类上的函数实现。其中Input函数和Output函数分别用于向可排序表中输入待排序序列,以及输出已经
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本科实验报告
课程名称:算法设计与分析实验项目:分治法合并排序实验地点:
专业班级:学号:
学生姓名:
指导教师:
实验一分治法合并排序
一、实验目的
1.掌握合并排序的基本思想
2.掌握合并排序的实现方法
3.学会分析算法的时间复杂度
4.学会用分治法解决实际问题
二、实验内容
随机产生一个整型数组,然后用合并排序将该数组做升序排列,要求输出排序前和排序后的数组。
三、实验环境
程序设计语言:c++
编程工具:microsoft visual studio 2010
四、算法描述和程序代码
#include<iostream.h>
#include<iomanip.h>
#include<stdlib.h>
#include<time.h>
#define M 11
typedef int KeyType;
typedef int ElemType;
struct rec{
KeyType key;
ElemType data; };
typedef rec sqlist[M];
class guibing{
public:
guibing(sqlist b) {
for(int i=0;i<M;i++)
r[i]=b[i];
}
void output(sqlist r,int n) {
for(int i=0;i<n;i++)
cout<<setw(4)<<r[i].key;
cout<<endl;
}
void xuanze(sqlist b,int m,int n) {
int i,j,k;
for(i=m;i<n-1;i++) {
k=i;
for(j=i;j<n;j++)
if(b[k].key>b[j].key) k=j;
if(k!=i)
{
rec temp=b[k];
b[k]=b[i];
b[i]=temp;
}
}
}
void merge(int l,int m,int h,sqlist r2){
xuanze(r,l,m);
xuanze(r,m,h);
output(r,M);
int i,j,k;
k=i=l;
for(j=m;i<m&&j<h;k++)
{
if(r[i].key<=r[j].key)
{
r2[k]=r[i];
i++;
}
else
{
r2[k]=r[j];
j++;
}
output(r2,M);
}
while(j<h)
{
r2[k]=r[j];
j++;k++;
}
while(i<=m)
{
r2[k]=r[i];
i++;
k++;
}
output(r2,M);
}
private:
sqlist r;
};
void main() {
cout<<"guibingfa1运行结果:\n";
sqlist a,b;
int i,j=0,k=M/2,n=M;
srand(time(0));
for(i=0;i<M;i++)
{
a[i].key=rand()%80;b[i].key=0;
}
guibing gx(a);
cout<<"排序前数组:\n";
gx.output(a,M);
cout<<"数组排序过程演示:\n";
gx.merge(j,k,n,b);
cout<<"排序后数组:\n";
gx.output(b,M);
cin.get(); }
五、实验结果截图
六、实验总结。