分治算法

分治是一种思想体现,就是把一个大的问题分为若干个子问题,这些子问题相互独立且与原问题性质相同然后在子问题继续向下分,一直到base cases,通过base cases的解决,一步步向上,最终解决最初的大问题。分治算法是递归的典型应用。

常见的利用分治算法思想的有 快速排序 以及 归并排序 等等。

快速排序:

又称为划分交换排序。快速排序是对冒泡排序的一种改进方法,在冒泡排序中,进行记录的关键字的比较和交换是在相邻记录之间进行,记录每次交换只能上移或者下移一个位置,而且总的比较和移动次数较多。在快速排序中。记录关键字的比较和记录的交换是从两端到中间进行的,待排序的关键字较大的就一次就能交换到后面的单元中,而关键字较小的记录一次就能够交换到前面的单元中,记录每次移动的记录较远,因此总的比较和移动次数较少,速度较快,故称为“快速排序”。(形象理解)

算法如下:

void  Partition(SeqList R ,int i, int j)
{                                         //对R[i]---R[j]区间内的记录进行一个划分排序
    RecType x=R[i];
    while(i<j){
        while(i<j&&R[j].key>=x.key)
            j--;                          //从 j 所指的位置向前搜索
        if(i<j){
          R[i] = R[j];
          i++;
        }
    while(i<j&&R[i].key<=x.key)
        i++;                              //从i所指的位置起向后搜索
    if(i<j){
        R[j]=R[i];j--;
      }
    }
   R[i] = x;
   return i;
}

有了一趟划分算法后,很容易写出快速排序的递归算法

void QuickSort(SeqList  R, int low, int high)
{
    int p;
    if(low<high){
         p = Partition(R, low,high);
         QuickSort(R, low,p-1);
         QuickSort(R, p+1,high);
    }
}  

从排序结果来看,快速排序是不稳定的,一般来说,快速排序有非常好的时间复杂度,它由于其他各种排序算法。可以证明,对n个记录进行快速排序的平均时间复杂度为O(nlog2n)。但是当待排序文件的记录已按照关键字有序或者基本有序时,复杂度反而增大了,原因是在第一趟快速排序中经过n-1次比较后,第一个记录仍然在它原来的位置上,并得到一个包含n-1个记录的子文件,第二次递归调用,经过n-2次比较,第二个记录仍定位在它原来的位置上,从而得到一个包括n-2个记录的子文件。以此类推。
这使得快速排序转变成冒泡排序,其时间复杂度为O(n²)。在这种情况下,可以对排序算法加以改进。从时间上分析,快速排序比其他排序算法要快;但从空间来看,由于快速排序的过程是递归的,因此需要一个栈空间实现递归,栈的大小取决于递归调用的深度。,栈的最大深度为[log2n]+1, 即使在最坏的情况下,栈的最大深度也不会超过n。因此,快速排序需要附加的空间为O(log2n)。

归并排序

归并排序的基本思想是:首先将待排序的文件看成n个长度为1的有序子文件,把这些子文件两两归并,得到n/2个长度为2的有序子文件;然后再把这n/2个有序的子文件两两归并,如此反复,最后得到一个长度为n的有序文件为止。这种排序方法称为二路归并排序。

二路归并排序中的核心操作是将数组中前后两个相邻的有序序列鬼秉承一个有序序列,其算法如下:

void Merge(SeqList R, SeqList MR, int low,int m, int high)
{
      int i,j,k;
      i = low; j=m+1;k=low;                    //初始化
      while(i<m &&j<= high)
          if(R[i].key<=R[j].key)
                MR[k++]=R[i++];
          else
                MR[k++]=R[j++];                 //将R[low..m]中剩余的复制到MR中
       while(j<=high)
                MR[k++] = R[j++];               //将R[m+1..high]中剩余的复制到MR
}

一趟归并排序的基本思想是,在某趟排序归并中,设各子文件长度为len(最后一个子文件长度可能会小于len),则归并前R[1..n]中共有[n/len]个有序子文件。调用归并操作对子文件进行归并时,必须对子文件的个数可能是奇数,最后一个子文件的长度可能小于len这两种特殊情况进行处理:若子文件个数为奇书,则最后一个子文件无需和其他子文件归并;若子文件个数为偶数,则要注意最后一对子文件中后一个子文件的区间上界为n。具体的一趟归并排序算法如下:

void  MergePass(SeqList  R, SeqList  MR, int len, int n)
{
      int i,j;
      for(i=1;i+2*len-1<=n;i=i+2*len)
            Merge(R,MR,i,i+len-1,i+2*len-1);
      if(i+len-1<n)                    //尚有两个子文件,其中最后一个长度小于len
            Merge(R,MR,i,i+len-1,n);     
      else                              //文件个数为奇数,最后一个子文件复制到MR中
            for(j=i;j<=n;j++)
                MR[j]=R[j];

}

整个归并排序算法如下:

void MergeSort()
{
      int len = 1;
      while(len<n)
           MergePass(R,MR,len,n);
           len = len*2;
           MergePass(MR,R,len,n);
           len = len*2;

}

二路归并排序的过程需要进行[log2n]趟。每一趟归并排序的操作,等于将两个有序子文件进行归并,而每一对有序子文件归并时,记录的比较次数均小于等于记录的移动次数,记录移动的次数均等于文件中记录的个数n,即每一趟归并的时间复杂度为0(n)。因此,二路归并的时间复杂度为O(nlog2n)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容

  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,732评论 0 15
  • 因为之前就复习完数据结构了,所以为了保持记忆,整理了一份复习纲要,复习的时候可以看着纲要想具体内容。 树 树的基本...
    牛富贵儿阅读 6,886评论 3 10
  • Divide-and-Conquer算法的设计 设计过程分为三个阶段: Divide:整个问题划分为多个子问题 C...
    三三de酒阅读 3,276评论 0 4
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,186评论 0 52
  • 人一定要有自己喜欢的事,并勇往直前的为之奋斗。 不然,它时不时的跳出来骚动你的心,让你觉得...
    暴躁的绿萝不开花阅读 176评论 0 0