学习笔记之递归和分治思想

递归,首先它的目的是把问题缩小为同类问题的子问题,通过不断地递归调用自身,最终到达某次调用能结束返回。

如果f()是一个递归函数,调用是这样的:

《学习笔记之递归和分治思想》

条件:递归到一定程度必须可以终止,不能无限地递归,换句话说,就是递归函数一定是可以结束的。

分治,对于一个规模为N的问题,若该问题可以容易解决,则直接解决,否则将其分解为M个规模较小的子问题,这些问题相互独立(这点很重要),并且和原问题形式相同,递归解决这些子问题,然后各子问题的解得到原问题的解。其运用的手段是递归思想。

条件:可以分解成几个相互独立的子问题。

几种运用递归和分治思想的算法:

1.快排

思路:选取一个参照数(一般为a[0]),将数组中比该参照数大的丢到参照数右边,比参照数小的丢到参照数左边,然后将参照数左边和右边分别重复(这里用到分治和递归),

void QuickSort(int a[],int left,int right)

{

        分割数组;

        QuickSort(a,left,参照数);

        QuickSort(a,参照数数右侧,right);

}

这个算法重点是分割数组,刚才谈到分割数组的方法“选取一个参照数(一般为a[0]),将数组中比该参照数大的丢到参照数右边,比参照数小的丢到参照数左边”,重点要理解这个“丢”,按照模拟现实的情景,第一个作为参照,遍历后面的数,遇到比其小的,丢到参照数左,剩下的就是比参照数大的了,但仔细想想,这里的“丢”,只能将参照数和遍历到的数交换,这一交换问题就来了,以前遍历过的比其大的数说不定又跑到参照数左边了。

到这里,我们梳理一下我们的目标:把一半数都换到右边来,把一半数都换到左边去,且左边数都小于右边数。

那要保证一点,当遍历到每个数时,该在右边的,本在右边则不换,不在右边必须要换到右边来(要求参照数得在右边),该在左边的,本在左边则不换,不在左边必须要换到左边来(参照数得在左边)。

最后思路:参照数在左边—-》遍历右边比参照数小的数,遍历到了换到右边来

                  参照数在右边—-》遍历左边比参照数大的数,遍历到了换到左边来

int Division(int a[],int left,int right)
{  
int base=a[left];
int l=left,r=right;

     if(l<r)   //递归结束条件

{

                  while(left<right)    //左右交替

      {

               while(left<right && a[left]<base)

                       left++;

              a[right]=a[left];   //遍历左边,遇到比参照数大的了,交换后,参照数移到左边来

              a[left]=base;

              while(left<right && a[right]>base)

                      right–;

              a[left]=a[right]; //遍历左边,遇到比参照数大的了,交换后,参照数移到右边来

              a[right]=base;

       }

            Division(a,l,right-1);  //左分治
   Division(a,left+1,r);  //右分治

}

}

缺点:输入量大时,递归栈大量开销









    原文作者:递归与分治算法
    原文地址: https://blog.csdn.net/xj2011xn/article/details/50070713
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞