zoukankan      html  css  js  c++  java
  • 从合并排序算法看“分治法”

    本文内容

    • 分治策略
    • 分治步骤
    • 从合并排序看“分治策略”

    分治策略

    分治法(divide-and-conquer),“分治法策略”是一种很重要的算法。顾名思义,“分而治之”。将原问题划分成 n 个规模较小,而结构与原问题相似的子问题;递归地解决这些子问题,然后再合并其结果,就得到原问题的解。

    “分治策略”是很多高效算法的基础,如快速排序、归并排序、傅立叶变换(快速傅立叶变换)。

    分治步骤

    • 分解(Divide):将原问题分解成一系列子问题;
    • 解决(Conquer):递归地解各个子问题。若子问题足够小,则直接求解;
    • 合并(Combine):将子问题的结果合并成原问题的解。

    备注:

    如何划分子问题的规模?从大量实践中发现,在用分治法设计算法时,最好使子问题的规模大致相同。换句话说,将一个问题分成大小相等的k个子问题的处理方法是行之有效的。许多问题可以取 k = 2。这种使子问题规模大致相等的做法是出自一种平衡(balancing)子问题的思想,它几乎总是比子问题规模不等的做法要好。

    从合并排序看“分治策略”

    合并排序(Merge Sort)算法完全按照上述模式,步骤如下:

    • 分解:将 n 个元素分成各含 n/2 个元素的子序列;
    • 解决:用合并排序发对两个子序列递归地排序;
    • 合并:合并两个已排序的子序列得到排序结果。
    元素头文件 MyElement.h
    #ifndef MYELEMENT_H_INCLUDED
    #define MYELEMENT_H_INCLUDED
     
    #define N 10
    #define LQ(a,b) ((a)<=(b))
     
    typedef int ElementType;
     
    void Print(ElementType e[], int n);
     
    #endif // MYELEMENT_H_INCLUDED
     
    元素源文件 MyElement.c
    #include <stdio.h>
    #include "MyElement.h"
     
    void Print(ElementType e[], int n)
    {
        int i;
        for(i=1; i<n; i++)
            printf("%d ",e[i]);
        printf("\n");
    }
     
    合并排序头文件 MergeSort.h
    #ifndef MERGESORT_H_INCLUDED
    #define MERGESORT_H_INCLUDED
     
    #include "MyElement.h"
     
    void MergeSort(ElementType e[], int n);
    void Main_MergeSort();
     
    #endif // MERGESORT_H_INCLUDED
     
    合并排序源文件 MergeSort.c
    #include <stdio.h>
    #include "MergeSort.h"
    #include "MyElement.h"
     
    void Merge(ElementType SR[],ElementType TR[],int i,int m,int n)
    {
        /* 将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n] */
        int j,k,l;
        for(j=m+1,k=i; i<=m&&j<=n; ++k) /* 将SR中记录由小到大地并入TR */
            if LQ(SR[i],SR[j])
                TR[k]=SR[i++];
            else
                TR[k]=SR[j++];
        if(i<=m)
            for(l=0; l<=m-i; l++)
                TR[k+l]=SR[i+l]; /* 将剩余的SR[i..m]复制到TR */
        if(j<=n)
            for(l=0; l<=n-j; l++)
                TR[k+l]=SR[j+l]; /* 将剩余的SR[j..n]复制到TR */
    }
    void MSort(ElementType SR[],ElementType TR1[],int s, int t)
    {
        /* 将SR[s..t]归并排序为TR1[s..t]。*/
        int m;
        ElementType TR2[N+1];
        if(s==t)
            TR1[s]=SR[s];
        else
        {
            m=(s+t)/2; /* 将SR[s..t]平分为SR[s..m]和SR[m+1..t] */
            MSort(SR,TR2,s,m); /* 递归地将SR[s..m]归并为有序的TR2[s..m] */
            MSort(SR,TR2,m+1,t); /* 递归地将SR[m+1..t]归并为有序的TR2[m+1..t] */
            Merge(TR2,TR1,s,m,t); /* 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t] */
        }
    }
    /* 归并排序 */
    void MergeSort(ElementType e[], int n)
    {
        MSort(e,e,1,n-1);
    }
     
    void Main_MergeSort()
    {
        ElementType d[N]= {49,38,65,97,76,13,27,49,55,10};
        printf("排序前:\n");
        Print(d,N);
        MergeSort(d,N);
        printf("排序后:\n");
        Print(d,N);
        printf("\n");
    }

    合并排序

    再者,若有一个数组,查找其中最大值和最小值,也可以采用分治算法。

    #include <stdio.h>
    #include <stdlib.h>
     
    #define M 10
     
    /*  求一个数组中最大值和最小值的分治算法
        参数:
       s 当前分治段的开始下标
       e 当前分治段的结束下标
       meter 表的地址
       max 存储当前搜索到的最大值
       min 存储当前搜索到的最小值
    */
    void MaxMin(int s,int e,int meter[],int *max,int *min)
    {
        int i;
        if(e-s <= 1)
        {
            if(meter[s] > meter[e])
            {
                if(meter[s] > *max)
                    *max = meter[s];
                if(meter[e] < *min)
                    *min = meter[e];
            }
            else
            {
                if(meter[e] > *max)
                    *max = meter[e];
                if(meter[s] < *min)
                    *min = meter[s];
            }
            return ;
        }
        i = s + (e-s)/2;
        MaxMin(s,i,meter,max,min);
        MaxMin(i+1,e,meter,max,min);
    }
     
    void main()
    {
        int meter[M]= {34,67,54,68,23,12,26,97,80,10};
        int max = INT_MIN; /* 用最小值初始化 */
        int min = INT_MAX; /* 用最大值初始化 */
        printf("The array's Max & Min Value as followed:\n");
        MaxMin(0,M - 1,meter,&max,&min); /* 分治法获取最值 */
        printf("\nMax : %d\nMin : %d\n",max,min);
    }

    求一个数组中最大值和最小值的分治算法

    下载 Demo

  • 相关阅读:
    钱多,人傻,快来快来
    Rabbitmq的使用及Web监控工具使用
    Fiddler的配置
    哪个微信编辑器比较好用?
    js手机号批量滚动抽奖代码实现
    Webform和MVC,为什么MVC更好一些?
    自学MVC看这里——全网最全ASP.NET MVC 教程汇总
    客如云系统访谈
    Asp.Net MVC2.0 Url 路由入门---实例篇
    架设自己的FTP服务器 Serv-U详细配置图文教程
  • 原文地址:https://www.cnblogs.com/liuning8023/p/2562747.html
Copyright © 2011-2022 走看看