分治与递归的结合-------快速排序

本文深入探讨了分治算法的思想及其与递归的关系,详细解释了如何利用递归来实现分治策略,尤其是在快速排序算法中的应用。

运用了分治的思想:为了解决一个大的问题,将一个规模为n的问题分解为规模较小的子问题,这些子问题互相独立并且和原问题相同。分别解这些子问题,最后将子问题的解合并                            得到原问题的解。比如实现n个数的快速排序可以分解为 基准点左侧的数的快速排序 和 基准点右侧的数的快速排序。并可以一直分治到只有1个数

运用了递归的手段实现分治。

 

第一种:

为什么要用递归:因为分治策略将大问题转化为与若干个与原问题解法相同的小问题,既然解法相同,原问题所用的函数  也就适用于若干个小问题。由于是若干个,不知道数量也                       就没有办法为每个小问题量身定做一个函数,就算知道数量,定做出的函数除了初始值不一样其他都一样。所以可以通过设置终止条件,确定初始值,来多次地调                       用原问题使用的函数。

怎么看待递归:  递归的其中一个重要部分是终止条件,终止条件明确了若干个究竟是多少个,究竟有多少个小问题。

                      递归的另一个重要部分就是通过一系列变换确定小问题的初始值,由于是多次调用,所以大问题与小问题一定存在某种联系

如何写递归函数 :  第一:明确原问题是什么,递归函数一定是 能解决原问题的函数 可以先假设一个条件(这个条件应该是原问题分解出来的小问题给出的解)来解决原问题,然后                                     用递归替代给出的条件。

                         第二:明确终止条件

                         第三:找出大问题与小问题之间的联系,即如何将大的问题转化为小的问题(最简单的就是阶乘了 大问题与小问题 大问题的规模n减去一就能转化为小问题)

                                  这也叫确定小问题的初始值。

 

写递归函数的步骤: 第一:分类讨论(其中包含终止条件 与 非终止条件  两者都可能不止一个)

                          第二:对于非终止条件,要对函数传入的n进行转化,转化为适用于小问题的n值,然后调用该递归函数解决这个小问题,并传回这个小问题的值

比如有 7 3 5 9 11 13 1 七个数

第一次调用递归的结果

int Partition(int arr[], int low, int high)    //划分算法,low为数组最小下标,high为数组最大下标,目的是为了找到基准点(基准点左侧的数小于等于它,右侧大于等于它)
{  
    int i, j, pivot;  
    i = low, j = high, pivot = arr[low];    //选择第一个数作为基准点
    while(i < j)  
    {  
        while(i < j && arr[j] >= pivot) --j;  
        if(i < j)   
            swap(arr[i++], arr[j]);   //交换 arr[i] 与 arr[j] 之后 i++ 
        while(i < j && arr[i] <= pivot) ++i;  
        if(i < j)   
            swap(arr[i], arr[j--]);  
    }  
    return j; //返回基准元素位置  
}  
  
void Quick_Sort(int arr[], int low, int high)  
{  
    int pivotpos;  
    if(low <= high)  
    {  
        pivotpos = Partition(arr, low, high);   //通过转化 找到小问题的基准点 pivotpos   确定了小问题的初始条件
        if(pivotpos > n / 2)  
            Quick_Sort(arr, low, pivotpos - 1); //基准左递归排序,知道low>high 递归返回,返回的成果在数组中,所以不需要return,一切更改都会保留在数组里
        else if(pivotpos < n / 2)  
            Quick_Sort(arr, pivotpos + 1, high); //基准右递归排序  
        else  
            mid = arr[pivotpos];  
    }  
}  

 

转载于:https://www.cnblogs.com/wshyj/p/6337873.html

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 8 2 2 1 3 7 6 6 8 4 1 1 5 9 9 6 10 4 4 5 5 0 9 10 10 12 12 13 0 0 17 18 18 12 11 13 13 17 17 16 18 14 11 11 15 19 16 16 20 14 14 15 15 19 19 20 20 4. 设计实现的提示 对2k×2k的棋盘可以划分成若干块,每块棋盘是原棋盘的子棋盘或者可以转化成原棋盘的子棋盘。 注意:特殊方格的位置是任意的。而且,L型条块是可以旋转放置的。 为了区分出棋盘上的方格被不同的L型条块所覆盖,每个L型条块可以用不同的数字、颜色等来标记区分。 5. 扩展内容 可以采用可视化界面来表示各L型条块,显示其覆盖棋盘的情况。 经典的递归问题, 这是我的大代码, 只是本人很懒, 不想再优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值