分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。
分治法解题的一般步骤:
(1)分解,将要解决的问题划分成若干规模较小的同类问题;
(2)求解,当子问题划分得足够小时,用较简单的方法解决;
(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。
简而言之,分治法的设计思想就是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
问题分析:以归并排序为例子,将待排序元素分成大小大致相同的2个子集合(递归直到最小的排序单元),分别对2个子集合进行排序,最终将排好序的子集合合并成为所要求的排好序的集合。下面我们用一张图来展示整个流程,最下面的(姑且叫他第一层)是原始数组分成了8个最小排序问题,各自只有一个元素,故不需要排序,大家可以看到,我们通过分而治之的思想把对最初数组的排序分为了若干个只有一个元素的小数组的排序,然后第二层,我们进行了合并,将每两个最小排序结果合并为有两个元素的数组,然后逐层往上进行合并,就有了最后的结果…
代码实现如下:
<pre name="code" class="objc">#include<stdio.h>
int L[100],R[100];
void merge(int numbers[],int left, int mid, int right)
{
int n1=mid-left+1;
int n2=right-mid;
int i,j,k;
for(i=1;i<=n1;i++)
L[i]=numbers[left+i-1];
for( j=1;j<=n2;j++)
R[j]=numbers[mid+j];
L[n1+1]=99999;
R[n2+1]=99999;
i=1;
j=1;
for(k=left;k<=right;k++)
if(L[i]<=R[j])
{
numbers[k]=L[i];
i++;
}
else
{
numbers[k]=R[j];
j++;
}
}
void mergeSort(int numbers[],int left, int right)
{
if(left<right)
{
int mid;
mid = (right + left) / 2;
mergeSort(numbers, left, mid);
mergeSort(numbers, mid+1, right);
merge(numbers,left, mid, right);
}
}
int main()
{
int numbers[]={5,2,4,6,1,3,2,6};
mergeSort(numbers,0,7);
for(int i=0;i<8;i++)
printf("%d",numbers[i]);
}
class Program
{
static int[] L=new int[100];
static int[] R=new int[100];
static void merge(int[] numbers,int left, int mid, int right)
{
int n1=mid-left+1;
int n2=right-mid;
int i,j,k;
for(i=1;i<=n1;i++)
L[i]=numbers[left+i-1];
for( j=1;j<=n2;j++)
R[j]=numbers[mid+j];
L[n1+1]=99999;
R[n2+1]=99999;
i=1;
j=1;
for(k=left;k<=right;k++)
if(L[i]<=R[j])
{
numbers[k]=L[i];
i++;
}
else
{
numbers[k]=R[j];
j++;
}
}
static void mergeSort(int[] numbers,int left, int right)
{
if(left<right)
{
int mid;
mid = (right + left) / 2;
mergeSort(numbers, left, mid);
mergeSort(numbers, mid+1, right);
merge(numbers,left, mid, right);
}
}
public static void Main(string[] args)
{
int[] numbers={5,2,4,6,1,3,2,6};
mergeSort(numbers,0,7);
for(int i=0;i<8;i++)
Console.Write(numbers[i]);
// TODO: Implement Functionality Here
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
归并排序算法的时间复杂度是O(nlogn),对于冒泡排序的O(n*n),效率还有有比较好的提高。其实本人原来在学习的时候好长一段时间不理解为什么时间复杂度会是O(nlogn),像冒泡排序就比较好理解,有两个for循环,问题的规模随着n变大而变大,算法时间复杂度自然就是O(n*n),后面花了一些时间来阅读一些资料才明白其原理,有兴趣的也可以去看看.简单的描述一下为什么会是O(nlogn)。大家看看,我们的例子,解一个8个元素的数组,我们用到了几层?是四层,假设我们这里有n个元素,我们会用到多少层?根据一定的归纳总结,我们知道我们会用到(lgn)+1层..(lgn)+1层需要用到lgn层次的合并算法.现在再看看MERGE
(A, p, q, r )的复杂度是多少,毫无疑问O(n),故其归并排序的算法时间复杂度是O(nlogn).当然这个结果还可以通过其他的方法计算出来,我这里是口语话最简洁的一种……
用归并算法,很好的解释了分治法的应用 , 希望对您有些帮助……
分享到:
相关推荐
课程的随堂作业,C语言的,用dev就能运行,萌新代码,勿喷,仅仅帮助不想写作业的朋友方便一下,反正老师也不会仔细检查的
课程的随堂作业,C语言的,用dev就能运行,萌新代码,勿喷,仅仅帮助不想写作业的朋友方便一下,反正老师也不会仔细检查的
c语言分治法求众数重数-五大常见算法策略之——递归与分治策略,算法数据结构 五大常用算法
主要是算法的课程设计,对分治法进行详细的分析和讲解,同时用java语言对其进行实现
在n枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,设计一个高效的算法来检测这枚假币。
分治法——归并排序 归并排序操作过程: def mergesort(seq): #归并排序 if len(seq) <= 1: return seq mid = int(len(seq) / 2) # 将列表分成更小的两个列表 # 分别对左右两个列表进行处理,分别返回两个...
算法设计与分析课内实验——分治法求众数。文档很齐全,包括算法分析过程和源代码(java语言eclipse环境)
%mergesort 分治算法——归并排序 %divide——将数组一分为二 %conquer——对两部分数组分别排序 %combine——将各自排好序的数组融合 %以此类推递归调用
第六章基本算法设计策略——分治法.pptx
1.暴力算法 2.分治法 1.暴力算法 2.分治法 1.暴力算法 2.分治法 1.准确性分析 2.性能分析 1.分治法的设计思想是,将一个难以直接解决的大问题,
掌握分治法解平面最接近点对算法设计思想、算法设计过程及程序编码实现。 采用分治法解最接近点对问题。请回答以下问题: 1)一维情形下如何用线性时间完成合并步骤? 2)二维情形下递归求解递归出口如何设置? 3)二维...
本资源为山东科技大学计算机算法设计与分析的实验报告,实现分治法求解棋盘问题算法,分析算法的复杂性。资料包含源码和实验报告,仅供参考,请勿抄袭! 在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的...
求最大字段的三种方法——_动态规划_蛮力_分治算法
问题:对于平面上给定的N个点,给出所有点对的最短距离,即,输入是平面上的N个点,输出是N点中具有最短距离的两点。
课程的随堂作业,C语言的,用dev就能运行,萌新代码,勿喷,仅仅帮助不想写作业的朋友方便一下,反正老师也不会仔细检查的
这个是二分检索的递归实现 具体的进去看看 有注释
算法详解系列图书共有4卷,本书是第1卷——算法基础。本书共有6章,主要介绍了4个主题,它们分别是渐进性分析和大O表示法、分治算法和主方法、随机化算法以及排序和选择。附录A和附录B简单介绍了数据归纳法和离散...
%divide——将数组分成两段 %conquer——每段分别求最大字段和 %combine——最大子段和无非三种情况:左端、右端、横跨中间 %每段分别求最大子段和的时候采用递归调用