`
zhaohaolin
  • 浏览: 1011213 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

递归算法

阅读更多

用三角数字问题说明递归

Int triangle(int n)

{

       if(n ==1)        //基值条件

              return 1;

       else

              return(n + triangle(n-1));              //递归调用自身

}

说明:导致递归的方法返回而没有再一次进行递归调用,这称为基值情况。

从上面可以看出递归方法的特征:

1, 调用自身

2, 当它调用自身的时候,它这样做是为了解决更小的问题

3, 存在某个足够简单的问题的层次,在这一层算法不需要调用自己就可以直接解答,且返回结果。

递归的效率问题:调用一个方法总要有一定的额外开销。控制必须从这个调用的位置转 移到这个方法的开始处。而且,传给这个方法的参数以及这个方法的返回的地址都要被压入一个内部的栈里。正因此,递归降低了执行效率。另外,中间参数以及返 回值要占内存,如果数据量大的话,可能会造成栈溢出。

递归的好处就在于它从概念上简化了问题

计算阶乘也是一个递归的经典例子,另外找两个数的最大公约数、求一个数的乘方等很多数学问题都可以用递归的思想来解决。

用递归方法解决变位字问题

假设要列出一个指定单词的所有变位字,也就是列出该词的全排列,它们都是由原来单词的字母组成。我们称这个工作是变位一个单词或称全排列一个单词。

解决思想:假设这个词有n个字母。

1, 全排列最右边的n-1个字母。

2, 轮换所有n个字母。

3, 重复以上步骤n次。

“轮换”这个词意味着所有的字母向左移一位,最左边的字母轮换至最右边字母的后 边。轮换单词n次以给每个字母排在开头的机会。当选定字母占据第一个位置时,所有其他字母被全排列。如何来全排列最右边的n-1个字母呢?通过递归,即调 用方法自身。每调用一次自身,全排列的字母数减少1,当词的大小只剩一个字母时即出现基值条件,方法返回。

       public static void doAnagram(int newSize)

       {

              if(newSize == 1)    //if too small,go no further

                     return;

              for (int j=0; j<newSize; j++) //for each position

              {

                     doAnagram(newSize - 1);      //anagram remaining

                     if (newSize == 2)   //if innermost,

                     {

                            displayWord();       //display it

                     }

                     rotate(newSize);     //rotate word

              }

       }

递归的二分查找

用最少的比较次数在一个有序的数组中找到给定的一个数据项。二分查找的方法是把数组从中间分为两半,然后看要查找的数据项在数组的哪一半,再次地折半,如此进行下去。下面是此方法的递归实现代码:

       private int recFind(long searchKey,int lowerBound,int upperBound)

       {

              int curIn;

              curIn = (lowerBound + upperBound) / 2;

              if(a[curIn]==searchKey)

                     return curIn;          //find it

              else                              //can't find it

              {

                     if (a[curIn] < searchKey)      //it's in upper half

                            return recFind(searchKey,curIn+1,upperBound);

                     else                                     //it's in lower half

                            return recFind(searchKey,lowerBound,curIn-1);

              }     //end else divide range

       }            //end recFind

二分查找是分治算法的一个例子。把一个大问题分成两个相对来说更小的问题,并且分别解决每一个小问题。对于每个小问题的解决方法也是一样的,每个小问题又分成两个更小的问题。一直持续下去直到达到易于求解的基值情况,就不用再分了。

分治算法通常是一个方法,在这个方法中含有两个对自身的递归调用,分别对应于问题的两个部分。在二分查找中,有两个这样的调用,不过只有一个真的执行。后面的归并排序是真正执行了两个递归调用。

归并排序

归并算法的中心是归并两个已经有序的数组。归并两个有序的数组AB,就生成了第三个数组C,数组C包含数组AB的所有数据项,并且使它们有序的排列在数组C中。做法就是用三个while循环,第一个循环沿AB走,比较它们的数据项,并且复制它们中较小的数据项到数组C。后面两个循环分别对应B的数据项已经全部移出,而C中还有剩余元素的情况,和B中还有剩余,C已经全部移出的情况。循环就是把数组中剩余的数据项复制到C中。

归并排序的思想是把一个数组分成两半,排序每一半,然后用归并方法把数组的两半归并成一个有序的数组。而为每一半进行排序,就用递归。即把每个一半都分成两个四分之一,对每个四分之一部分排序,然后把它们归并成一个有序的一半。

归并排序的基值条件,就是当发现mergeSort()方法发现只有一个数据项的数组时,它就返回。把这两个数据项归并到一个有两个数据项的数组中。还要建一个工作空间数组,,它和初始数组一样大小。归并得到的数组存储到工作空间数组中,每一次归并完成之后,工作数组的内容被复制回原来的数组中。

归并排序的运行时间是O(N*logN)

下面是归并排序的完整代码:

 

class MergeSortApp
{
    
private static long[] theArray;
    
private static int nElems;

    
public static void display()
    
{
        
for(int j=0;j<nElems;j++)
            System.out.print(theArray[j] 
+ " ");
        System.out.println(
"");
    }


    
public static void mergeSort()
    
{
        
long[] workSpace = new long[nElems];    //provides workspace
        recMergeSort(workSpace,0,nElems-1);
    }


    
private static void recMergeSort(long[] workSpace,int lowerBound,int upperBound)
    
{
        
if(lowerBound == upperBound)    //if range is 1,no use sorting
            return;
        
else
        
{                                
            
int mid = (lowerBound+upperBound)/2;    //find midpoint

            recMergeSort(workSpace,lowerBound,mid);    
//sort low half

            recMergeSort(workSpace,mid
+1,upperBound);    //sort high half

            merge(workSpace,lowerBound,mid
+1,upperBound);    //merge them
        }

    }


    
private static void merge(long[] workSpace,int lowPtr,int highPtr,int upperBound)
    
{
        
int j=0;        //workspace index
        int lowerBound = lowPtr;    //因为随着归并的进行,lowPtr会变化,lowerBound变量用于记住该变量,
                                    
//以备将归并后的数据拷贝回原数组时使用
        int mid = highPtr-1;
        
int n = upperBound-lowerBound+1;        //# of items

        
while (lowPtr <= mid && highPtr <= upperBound)
        
{
            
if(theArray[lowPtr] < theArray[highPtr])
                workSpace[j
++= theArray[lowPtr++];
            
else
                workSpace[j
++= theArray[highPtr++];
        }


        
while (lowPtr <= mid)
        
{
            workSpace[j
++= theArray[lowPtr++];            
        }


        
while (highPtr <= upperBound)
        
{
            workSpace[j
++= theArray[highPtr++];
        }


        
for (j=0; j<n; j++)
        
{
            theArray[lowerBound
+j] = workSpace[j];
        }

    }

    
    
public static void main(String[] args) 
    
{
        theArray 
= new long[]{64,21,33,70,12,85,44,3,99,0,108,36};
        nElems
=12;

        display();    
//display items

        mergeSort();    
//merge sort the array

        display();    
//display again
    }

}

 

消除递归:递归和栈有紧密的联系,大部分编译器都是使用栈来实现递归的。可以用栈实现把递归算法转换成非递归的算法

递归应用

求一个数的乘方:基于xy次方等于x*xy/2次方这个原理

背包问题:从选择第一个数据项开始,剩余的数据项的加和必须符合背包的目标重量减去第一个数据项的重量;这是一个新的目标重量。逐个试每种数据项组合的可能性,如果没有组合合适的话,放弃第一个数据项,并且从第二个数据项开始再重复整个过程。依次进行下去。

组合问题:从n个人中选出k个组队,有多少种组合?(n,k= (n-1, k-1) + (n, k-1)

分享到:
评论

相关推荐

    VC对磁盘文件遍历搜索的递归算法和非递归算法

    在VC++(Visual C++)环境中,有多种方法可以实现这一目标,其中最常见的是递归算法和非递归算法。这两种方法各有优缺点,适用于不同的场景。 **递归算法**: 递归算法是一种基于函数自身调用解决问题的方法。在...

    5!递归算法和非递归算法

    递归算法和非递归算法 在计算机科学与编程领域中,递归算法与非递归算法是两种非常重要的计算方法。本文将详细介绍这两种算法的特点、应用场景以及如何实现它们,特别针对初学者及面试准备者。 #### 递归算法 ...

    acm递归算法总结竞赛

    在ACM(国际大学生程序设计竞赛)中,递归算法是一种常见的解决问题的方法,它通过函数自身调用自身来实现问题的解决。递归的核心在于找到基本情况(base case),即可以直接求解的问题,以及每次递归调用时问题规模...

    .net 递归算法 .net 递归算法.net 递归算法

    在.NET编程环境中,递归算法是一种强大的工具,它允许函数或方法调用自身来解决复杂问题。递归的核心思想是将大问题分解为相同或相似的小问题,直到问题变得足够简单,可以直接得出答案。这种解决问题的方式在数据...

    abap简单递归算法

    ### ABAP简单递归算法解析 #### 一、引言 ABAP(Advanced Business Application Programming)是一种用于SAP系统的编程语言。它不仅支持传统的过程化编程,还支持面向对象编程和Web开发。本文将深入探讨一个ABAP中...

    递归算法与循环算法的分析

    递归算法与循环算法的分析 递归算法是指在程序设计中,在调用一个函数的过程中又出现直接或间接调用其函数本身的现象。递归算法的优点是编写容易,结构清晰,可读性强,但是其缺点是计算速度慢,时间花费较长,效率...

    汉诺塔问题的非递归算法

    非递归算法解决了这个问题,提供了一个不同于传统递归解决方案的方法。对于n个圆盘的情况,非递归算法的核心在于通过交替执行两个步骤来移动圆盘: 1. **步骤1**:根据圆盘数量的奇偶性,按顺时针方向将圆盘1从当前...

    Hanoi塔问题的一种非递归算法

    ### Hanoi塔问题的一种非递归算法:深入解析与实现 #### 一、引言 Hanoi塔问题作为计算机科学领域内经典的递归问题之一,因其简洁性和挑战性而广受关注。通常,Hanoi塔问题的解决方案多采用递归算法,尽管其逻辑...

    递归算法ppt让你快速上手

    "递归算法ppt让你快速上手" 递归算法是计算机科学中的一种重要算法思想,它可以解决许多复杂的问题。下面是递归算法的知识点总结: 1. 递归的定义:若一个对象部分地包含它自己,或用它自己给自己定义,则称这个...

    合并排序递归和非递归算法

    3. **可读性和实现难度**:递归算法通常代码简洁,易于理解,而非递归算法可能需要更复杂的逻辑来模拟递归行为。 总的来说,选择哪种实现方式取决于具体场景,如内存限制、性能要求以及代码的可读性等。递归版本的...

    中序遍历二叉树非递归算法

    在IT领域,尤其是在数据结构与算法的学习中,中序遍历二叉树的非递归算法是一个关键且实用的知识点。通常,我们首先通过递归来实现二叉树的遍历,但递归方法可能因深度过大导致栈溢出,因此掌握非递归版本的遍历算法...

    程序设计中递归算法

    ### 递归算法在程序设计中的应用 #### 一、递归的概念与本质 递归是一种重要的编程思想,在计算机科学和数学领域都有广泛的应用。它指的是一个过程或函数直接或间接地调用自身来解决问题的方法。递归的核心在于将...

    快速排序算法设计与分析总结 二叉树与树的转换前序、后序的递归、非递归算法,层次序的非递归算法的实现

    快速排序算法设计与分析总结 二叉树与树的转换前序、后序的递归、非递归算法,层次序的非递归算法的实现 二叉树与树的转换前序、后序的递归、非递归算法,层次序的非递归算法的实现,应包含建树的实现 实现树与...

    递归算法专题ppt

    ### 递归算法专题知识点详解 #### 一、递归算法原理 递归算法是一种将问题分解成子问题的方法,其中子问题与原问题性质相同但规模较小。递归算法的关键在于识别出能够通过递归解决的问题,并找到递归的基本情况...

    利用递归算法求阶乘(VB6.0源代码)利用递归算法求阶乘

    在这个主题中,我们将深入探讨如何使用递归算法在VB6.0(Visual Basic 6.0)中计算阶乘。VB6.0是Microsoft开发的一款经典可视化编程环境,用于创建Windows应用程序。 阶乘是一个数学概念,表示一个正整数n的所有...

    递归算法的详解,各种常见递归算法

    递归算法是一种强大的编程技术,它通过函数或过程在解决问题时调用自身来解决更小规模的相同问题。递归的基本概念在于一个函数在定义中包含对自身的引用,或者问题的解决方案依赖于较小规模问题的解决方案。在程序...

    程序2_delphi_milemut_递归算法_

    在编程领域,递归算法是一种强大的工具,尤其在处理树形结构或遍历目录时显得尤为重要。本项目“程序2_delphi_milemut_递归算法”是使用Delphi编程语言实现的一个应用,旨在通过递归方法列出指定目录“C:\Windows\...

    Python基于递归算法实现的走迷宫问题

    ### Python基于递归算法实现的走迷宫问题详解 #### 一、递归算法简介 在探讨如何使用Python实现走迷宫问题之前,我们先来了解一下递归算法的基本概念及其应用场景。 **递归**是一种非常重要的算法思想,在计算机...

    递归算法应用:删除某一个节点的子树算法

    递归算法应用:删除某一个节点的子树算法 递归算法是计算机科学中的一种重要算法设计技术,通过将问题分解成更小的子问题,以解决复杂的问题。在数据结构中,递归算法广泛应用于树形结构的操作,例如二叉树的遍历、...

Global site tag (gtag.js) - Google Analytics