实验三分治算法.doc

合集下载

算法设计与分析实验三

算法设计与分析实验三

实验三分治算法(2)一、实验目的与要求1、熟悉合并排序算法(掌握分治算法)二、实验题1、问题陈述:对所给元素存储于数组中和存储于链表中两中情况,写出自然合并排序算法.2、解题思路:将待排序元素分成大小大相同的两个集合,分别对两个集合进行排序,最终将排好序的子集合合并成为所要求的排好序的集合.自然排序是通过一次扫描待排元素中自然排好序的子数组,再进行子数组的合并排序.三、实验步骤程序代码:#include <iostream.h>const int N=100;//定义不可变常量N//各个函数的声明void ScanTarget(int target[], int n, int head[], int tail[]);int CountHead(int head[]);void MergeSort(int a[], int head[], int tail[], int m);void MergePass(int x[], int y[], int s, int a[], int b[], int m);void Merge(int c[], int d[], int l, int m, int r);//主函数的定义void main(){char a;do{int target[N],head[N],tail[N];int i=0,n,m;for(; i<N; i++){head[i]=-1;tail[i]=-1;}cout<<"请输入需要排序的数列的总数:"<<endl;cin>>n;cout<<"请输入需要排序的数列:" <<endl;for(i=0; i<n; i++)cin>>target[i];ScanTarget(target,n,head,tail);m=CountHead(head);//调用求长度的函数MergeSort(target,head,tail,m);//调用归并排序函数cout<<"排序后:"<<endl;for(i=0; i<n; i++)cout<<target[i]<<" ";cout<<endl;cout<<"是否继续(y/n):"<<endl;cin>>a;}while(a!='n' && a!='N');}void ScanTarget(int target[], int n, int head[], int tail[])//定义扫描待排数组的函数;{int i,j=0,k=0;head[k]=0;k++;for(i=1;i<n;i++){if(target[i-1]>target[i]){tail[j++]=i-1;head[k++]=i;}}tail[j]=n-1;}int CountHead(int head[])//定义求长度的函数;{int i(0);while(head[i]!=-1){i++;}return i;//返回长度值}void MergeSort(int a[], int head[], int tail[], int m)//定义归并排序算法{int b[N];int s=1;while(s<m){MergePass(a,b,s,head,tail,m);s+=s;MergePass(b,a,s,head,tail,m);s+=s;}}void MergePass(int x[], int y[], int s, int a[], int b[], int m)//合并输出{int i=0;while(i <= m-2*s){Merge(x,y,a[i],b[i+s-1],b[i+2*s-1]);i=i+2*s;}if(i+s < m){Merge(x,y,a[i],b[i+s-1],b[m-1]);}else{for(int j=i; j<m; j++)for(int k=a[j]; k<=b[j]; k++)y[k]=x[k];}}void Merge(int c[], int d[], int l, int m, int r)//合并已经排序的两个数组,即归并操作{int i,j,k;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];}}程序运行结果如下所示:请输入需要排序的数列的总数:5请输入需要排序的数列:13 78 34 5 66排序后:5 13 34 66 78是否继续(y/n):nPress any key to continue。

3分治法

3分治法

二分搜索算法分析
• 时间复杂度分析: 1 若n=1 C(n)= C( n / 2 )+1 若n ≥ 2 求解递推式得:
c(n) = log n + 1
6.3 合并排序
• 原问题:对A[1...n]排序 • 用分治策略分析: (1)划分:将A[1...n]分为A[1...n/2] A[n/2+1...n]两部分; (2)治理: 分别对A[1...n/2] 和 A[n/2+1...n]排序 (3)组合:将两个有序子序列合并为一 个有序序列
合并排序算法分析
• 时间复杂度分析: 0 若n=1 C(n)= 2C( n / 2 )+n-1 若n≥2 求解递推式得: C(n)=nlogn-n+1
思考题:求数组的“逆序对” 思考题:求数组的“逆序对”个 数
• Sort公司是一个专门为人们提供排序服务的公 司,该公司的宗旨是“顺序是最美丽的”。 他们的工作是通过一系列移动,将某些物品 按顺序摆好。他们的服务是通过工作量来计 算的,即移动东西的次数。所以,在工作前 必须先考察工作量,以便向用户提出收费数 目。 • 用户并不需要知道精确的移动次数,实际上, 大多数人是凭感觉来认定这一列物品的混乱 程度。
分治法的基本步骤
divide-and-conquer(P) { if ( | P | <= n0) adhoc(P); //解决小规模的问题 divide P into smaller subinstances P1,P2,...,Pk;//分解问题 for (i=1,i<=k,i++) yi=divide-and-conquer(Pi); //递归的解各子问题 return merge(y1,...,yk); //将各子问题的解合并为原问题的解 } 人们从大量实践中发现,在用分治法设计算法时, 最好使子问题的规模大致相同。即将一个问题分成 大小相等的k个子问题的处理方法是行之有效的。 这种使子问题规模大致相等的做法是出自一种平衡 平衡 (balancing)子问题 子问题的思想,它几乎总是比子问题 子问题 规模不等的做法要好。

实验三 分治算法

实验三 分治算法

实验三分治算法(4学时)
一、实验目的与要求
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、在快速排序中,记录的比较和交换是从两端向中间进行的,关键字较大的记录一次就能交换到后面单元,关键字较小的记录一次就能交换到前面单元,记录每次移动的距离较大,因而总的比较和移动次数较少。

三、实验提示
1、用i,j做参数,且采用传递引用或指针的形式带回值。

2、。

分治算法的实验报告

分治算法的实验报告

一、实验背景分治算法是一种常用的算法设计方法,其基本思想是将一个复杂问题分解成若干个相互独立的小问题,然后将小问题递归求解,最终将子问题的解合并为原问题的解。

分治算法具有高效性、可扩展性和易于实现等优点,被广泛应用于各个领域。

本实验旨在通过实现分治算法解决实际问题,掌握分治算法的设计思想,并分析其时间复杂度。

二、实验目的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 次实验if(maxi>maxj)max=maxi;elsemax=maxj;if(mini<minj)min=mini;elsemin=minj;return;}}srand((unsigned int)time(NULL));cout <〈”随机产生的数据(0—100):”;for(int i=0; i〈m; i++)a[i] = rand()%100;测试结果附录:完整代码SelectMaxMin.cpp:#include <iostream>#include <ctime>#include 〈cstdio>#include <iomanip>#include 〈cstdlib〉using namespace std;void SelectMaxMin(int *a,int i,int j,int &max,int &min) {if(i==j){max= a[i];min =a[i];return;}else{int mid=(i+j)/2;int maxi,maxj,mini,minj;SelectMaxMin(a,i,(i+j)/2,maxi,mini);SelectMaxMin(a,((i+j)/2)+1,j,maxj,minj);if(maxi〉maxj)max=maxi;elsemax=maxj;if(mini<minj)min=mini;elsemin=minj;return;}}int main(){clock_t start,end,over;start=clock();end=clock();over=end—start;start=clock();//freopen("in。

txt",”r",stdin);//freopen(”out。

txt”,”w",stdout);int m;cout 〈<"Please input the number : ”;cin>〉 m;int a[m];srand((unsigned int)time(NULL));cout 〈〈 "随机产生的数据(0-100):";for(int i=0; i〈m; i++)a[i] = rand()%100;for(int i=0; i〈m; i++)cout <〈 a[i] 〈< " ";cout 〈< endl;int max,min;SelectMaxMin(a,0,m-1,max,min);cout 〈< "max = " 〈〈 max 〈〈 endl;cout <〈”min = " <〈 min 〈〈 endl;end=clock();printf(”The time is %6.3f”,(double)(end-start—over)/CLK_TCK); }。

分治算法实验报告.doc

分治算法实验报告.doc

一、实验目的1.加深对分治算法的基本思想、基本步骤和一般形式的理解,掌握分治算法设计的基本方法。

2.用分治法设计L型组件填图问题的算法,分析其复杂性,并实现;3.用分治法设计求数列中的第1~k小元素的算法,分析其复杂性,并实现。

二、实验内容(一)L型组件填图问题1.问题描述设B是一个n×n棋盘,n=2k,(k=1,2,3,…)。

用分治法设计一个算法,使得:用若干个L型条块可以覆盖住B的除一个特殊方格外的所有方格。

其中,一个L型条块可以覆盖3个方格。

且任意两个L型条块不能重叠覆盖棋盘。

例如:如果n=2,则存在4个方格,其中,除一个方格外,其余3个方格可被一L型条块覆盖;当n=4时,则存在16个方格,其中,除一个方格外,其余15个方格被5个L型条块覆盖。

2. 具体要求输入一个正整数n,表示棋盘的大小是n*n的。

输出一个被L型条块覆盖的n*n棋盘。

该棋盘除一个方格外,其余各方格都被L型条块覆盖住。

为区别出各个方格是被哪个L型条块所覆盖,每个L型条块用不同的数字或颜色、标记表示。

3. 测试数据(仅作为参考)输入:8输出:A 2 3 3 7 7 8 82 2 13 7 6 6 84 1 15 9 96 104 45 5 0 9 10 1012 12 13 0 0 17 18 1812 11 13 13 17 17 16 1814 11 11 15 19 16 16 2014 14 15 15 19 19 20 204. 设计与实现的提示对2k×2k的棋盘可以划分成若干块,每块棋盘是原棋盘的子棋盘或者可以转化成原棋盘的子棋盘。

注意:特殊方格的位置是任意的。

而且,L型条块是可以旋转放置的。

为了区分出棋盘上的方格被不同的L型条块所覆盖,每个L型条块可以用不同的数字、颜色等来标记区分。

5. 扩展内容可以采用可视化界面来表示各L型条块,显示其覆盖棋盘的情况。

(二) 求第k小项三、程序清单及实验过程和结果分析(一)#include "stdafx.h"#include "stdio.h"#define M 1024int table[M][M];int index;void LFill( int startx , int starty , int width , int x , int y ){int half=width/2;if( width==2 ){//填充if( table[startx][starty]==0 ) table[startx][starty]=index;if( table[startx+1][starty]==0 ) table[startx+1][starty]=index;if( table[startx][starty+1]==0 ) table[startx][starty+1]=index;if( table[startx+1][starty+1]==0 ) table[startx+1][starty+1]=index;index++;}else{//判断x,y方块位置//根据该位置用L填充if( x < startx+half ){if( y < starty+half ) //左上{table[startx+half-1][starty+half]=index; //左下table[startx+half][starty+half-1]=index; //右上table[startx+half][starty+half]=index; //右下index++;LFill(startx,starty,half,x,y);LFill(startx,starty+half,half,startx+half-1,starty+half);//左下LFill(startx+half,starty,half,startx+half,starty+half-1);//右上LFill(startx+half,starty+half,half,startx+half,starty+half);//右下}else{//左下table[startx+half-1][starty+half-1]=index; //左上table[startx+half][starty+half-1]=index; //右上table[startx+half][starty+half]=index; //右下index++;LFill(startx,starty,half,startx+half-1,starty+half-1);//左上LFill(startx,starty+half,half,x,y);LFill(startx+half,starty,half,startx+half,starty+half-1);//右上LFill(startx+half,starty+half,half,startx+half,starty+half);//右下}}else{if( y<starty+half )//右上{table[startx+half-1][starty+half]=index;table[startx+half-1][starty+half-1]=index;table[startx+half][starty+half]=index;index++;LFill(startx,starty,half,startx+half-1,starty+half-1);//左上LFill(startx,starty+half,half,startx+half-1,starty+half);//左下LFill(startx+half,starty,half,x,y);LFill(startx+half,starty+half,half,startx+half,starty+half);//右下}else{//右下table[startx+half][starty+half-1]=index;table[startx+half-1][starty+half-1]=index;table[startx+half-1][starty+half]=index;index++;LFill(startx,starty,half,startx+half-1,starty+half-1);//左上LFill(startx,starty+half,half,startx+half-1,starty+half);//左下LFill(startx+half,starty,half,startx+half,starty+half-1);//右上LFill(startx+half,starty+half,half,x,y);}}}}int main(){index=1;int n,i,j,p,q;printf("输入n的大小(n=2^k):");scanf("%d",&n);for(i=0;i<n;i++)for(j=0;j<n;j++)table[i][j]=0;printf("输入特殊位置坐标:");scanf("%d%d",&p,&q);table[p][q]=-1;LFill(0,0,n,p,q);for(i=0;i<n;i++){for(j=0;j<n;j++){if(i==p&&j==q) printf(" A");elseprintf("%5d",table[i][j]);}printf("\n");}}(二)#include "stdafx.h"#include "stdio.h"#define M 100void sort(int a[],int n){int i,j,t;for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)if(a[i]>a[j]){t=a[i];a[i]=a[j];a[j]=t;}}int select(int a[],int low,int high,int k){int pp=low+high-1;if(pp<44){sort(a,high);return a[k];}int b[50],c[50];int i=1,j=1,t=1;for(i=1;i<=high;i++)//对每组排序后分别取中项存于数组c中,再对数组c排序{b[j++]=a[i];if( i % (high/5) ==0 || i==high){sort(b,j-1);c[t++]=b[j/2];j=1;}}int mid=t/2;sort(c,t-1);int aa[50],bb[50],cc[50];int p=1,q=1,r=1;for(i=1;i<=high;i++){if(a[i]>c[mid]) cc[r++]=a[i];else if(a[i]<c[mid]) aa[p++]=a[i];else if(a[i]==c[mid]) bb[q++]=a[i];}p--;q--;r--;if(p>=k) return select(aa,1,p,k);else if( (p+q) >=k) return c[mid];else return select(cc,1,r,k-p-q);}int main(){int n,a[100],i,k;scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d",&a[i]);scanf("%d",&k);printf("第%d小项为:%d\n",k,select(a,1,n,k) );return 0;}。

分治算法实验(用分治法查找数组元素的最大值和最小值)

分治算法实验(用分治法查找数组元素的最大值和最小值)

算法分析与设计实验报告第一次实验附录:完整代码(分治法)#include<iostream>#include<time.h>#include<iomanip>using namespace std;//当数组中的元素个数小于3时,处理最大值int compmax(int A[],int start,int end){int max;if(start<end) //有两个元素{if(A[start]<=A[end])max=A[end];elsemax=A[start];}else//有一个元素max=A[start];return max;}//当数组中元素的个数小于2时,处理最小值int compmin(int A[],int start,int end){int min;if(start<end) //有两个元素{if(A[start]<=A[end])min=A[start];elsemin=A[end];}else//有一个元素min=A[start];return min;}//分治法处理整个数组,求最大值与最小值void merge(int a[],int left,int right,int &Max,int &Min) //Max,Min用来保存最大值与最小值//之所以使用&引用,是由于如果只是简单的使用变量,并不会改变Max与Min的值,使用指针也可以{int max1=0,min1=0,max2=0,min2=0;if(right-left>2) //当数组中元素个数大于等于3时,进行分治{int mid=(right+left)/2;merge(a,left,mid,max1,min1); //左半边递归调用自身,求出最大值最小值,分别保存在max1,min1中merge(a,mid+1,right,max2,min2); //右半边递归调用自身,求出最大值最小值,分别保存在max2,min2中if(max1>=max2) //子序列两两合并,求出最大值与最小值,保存在Max与Min中Max=max1;elseMax=max2;if(min1<=min2)Min=min1;elseMin=min2;}else//数组中元素个数小于3时的情况,直接赋值{Max=compmax(a,left,right);Min=compmin(a,left,right);}}void ran(int *input,int n) //随机生成数组元素函数{int i;srand(time(0));for(i=0;i<n;i++)input[i]=rand();input[i]='\0';}int a[1000000]; //定义全局变量用来存放要查找的数组int main(){int n;int i;int max;int min;cout<<"请输入要查找的序列个数:"<<endl;for(i=0;i<5;i++){cin>>n;ran(a,n);clock_t start,end,over; //计算程序运行时间的算法start=clock();end=clock();over=end-start;start=clock();merge(a,0,n-1,max,min); //调用分治法算法cout<<max<<" "<<min<<endl;end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显示运行时间}system("pause"); //停止运行窗口return 0;}完整代码(非递归方法)#include<iostream>#include<time.h>#include<iomanip>using namespace std;void ran(int *input,int n) //随机生成数组元素函数{int i;srand(time(0));for(i=0;i<n;i++)input[i]=rand();input[i]='\0';}int a[1000000];int main(){int max=a[0],min=a[0];int i,j,n;cout<<"请输入数据规模:"<<endl;for(j=0;j<5;j++){cin>>n;ran(a,n);clock_t start,end,over; //计算程序运行时间的算法start=clock();end=clock();over=end-start;start=clock();for(i=1;i<n;i++){if(a[i]>max)max=a[i];if(a[i]<min)min=a[i];}cout<<max<<" "<<min<<endl;end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显示运行时间}system("pause");return 0;}。

分治法实验报告

分治法实验报告

分治法实验报告分治法实验报告一、引言分治法是一种重要的算法设计策略,它将一个大问题分解成若干个小问题,并通过递归的方式解决这些小问题,最终将它们的解合并起来得到原问题的解。

本实验旨在通过实际案例,探索分治法的应用和效果。

二、背景在计算机科学领域,分治法常常被用于解决一些复杂的问题,如排序、搜索、图算法等。

它的核心思想是将问题划分为更小的子问题,然后分别解决这些子问题,最后将它们的解合并起来得到原问题的解。

通过这种方式,我们可以降低问题的复杂度,提高算法的效率。

三、实验目的本实验旨在通过实际案例,验证分治法在问题解决中的有效性,并探索其在不同问题上的应用效果。

通过对比不同算法的运行时间和结果准确性,评估分治法在不同场景下的适用性。

四、实验过程本次实验选取了两个典型的问题,分别是最大子数组和快速排序。

首先,我们使用分治法来解决最大子数组问题。

该问题要求在一个给定的数组中,找到一个连续子数组,使得该子数组的和最大。

我们将数组分为两半,分别求解左半部分和右半部分的最大子数组,然后再考虑跨越中点的最大子数组。

通过递归的方式,最终得到整个数组的最大子数组。

接着,我们使用分治法来实现快速排序算法。

快速排序是一种高效的排序算法,它的核心思想是通过选择一个基准元素,将数组分为两个部分,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素。

然后,对左右两个部分分别递归地进行快速排序,最终得到有序的数组。

五、实验结果通过对最大子数组和快速排序问题的实验,我们得到了以下结果。

首先,分治法在解决最大子数组问题上表现出色。

通过将问题划分为更小的子问题,我们可以在较短的时间内找到最大子数组,大大提高了算法的效率。

其次,在快速排序问题上,分治法同样展现了强大的能力。

通过不断地划分数组并进行排序,我们可以快速得到有序的结果。

六、实验分析分治法作为一种重要的算法设计策略,具有许多优点。

首先,它可以将复杂的问题分解为简单的子问题,降低了问题的复杂度,提高了算法的效率。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

华东师范大学计算机科学技术系上机实践报告
课程名称:算法设计与分析年级:05上机实践成绩:
指导教师:柳银萍姓名:
上机实践名称:分治算法学号:上机实践日期:2007-4-24
上机实践编号:NO.3组号:上机实践时间:10:00-11:30
一、目的
二、内容与设计思想
1.在一个数组A[1..n] 中,同时寻找最大值和最小值[假设n 为2 的方幂]。

并给出你的算法的复杂度分析。

要求:
输入:第一行为一个正整数N(0<N<=500000),表示数组中有多少个元素,当N<=0时表示输入结束。

接下来一行中有N个数。

表示数组A中的元素,这些数不超过65535。

输出:输出最大元素和最小元素,输出见sample。

每个Case之间用一个空行隔开。

1.1其思路是:
1.2具体算法是:
1.3其复杂度分析
2.给出一个分治算法,在一个具有n 个数的数组中找出第二个最大元素。

要求:
输入:第一行为一个正整数N(0<N<=500000),表示数组中有多少个元素,当N<=0时表示输入结束。

接下来一行中有N个数,表示数组A中的元素,这些数不超过65535。

输出:输出第二个最大元素,每一个输出占一行。

2.1其思路是:
2.2具体算法是:
3.给出一个分治算法,计算两个n 位大整数的乘积。

即A*B.并给出你的算法的复杂度分
析。

要求:
输入:输入有多组测试数据,每个输入占两行,第一行表示整数A,第二行表示整数B。

.
输出:输出A*B。

3.1其思路是:
3.2具体算法是:
3.3其复杂度分析:
三、使用环境
四、调试过程
五、总结
六、附录
1. 求最值问题的程序:
(此处放程序)
运行结果:
2. 求次最大值问题的程序:
(此处放程序)
运行结果:
3.大整数乘积问题的程序:
(此处放程序)
运行结果:
要求至少给出1组测试数据运行结果。

相关文档
最新文档