博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一些经典递归算法
阅读量:6917 次
发布时间:2019-06-27

本文共 14648 字,大约阅读时间需要 48 分钟。

hot3.png

递归

递归是一种方法(函数)调用自己的编程技术。

1.三角数字

1,3,6,10,15,21,...

使用递归查找第N项是几

// triangle.java// evaluates triangular numbers// to run this program: C>java TriangleAppimport java.io.*;class TriangleApp   {   static int theNumber;   public static void main(String[] args) throws IOException      {      System.out.print("Enter a number: ");      theNumber = getInt();      int theAnswer = triangle(theNumber);      System.out.println("Triangle="+theAnswer);      }  // end main()//-------------------------------------------------------------   public static int triangle(int n)      {      if(n==1)         return 1;      else         return  ( n + triangle(n-1) );      }//-------------------------------------------------------------   public static String getString() throws IOException      {      InputStreamReader isr = new InputStreamReader(System.in);      BufferedReader br = new BufferedReader(isr);      String s = br.readLine();      return s;      }//-------------------------------------------------------------   public static int getInt() throws IOException      {      String s = getString();      return Integer.parseInt(s);      }//--------------------------------------------------------------   }  // end class TriangleApp

2.变位字

变位字实际上就是高中学的排列,几个不同的字母共有几种不同的排列方法。如a.b.c共有8中排列方法。下面是其算法,该算法打印的结果是所有的排列结果。

// anagram.java// creates anagrams// to run this program: C>java AnagramAppimport java.io.*;class AnagramApp   {   static int size;   static int count;   static char[] arrChar = new char[100];   //-----------------------------------------------------------   public static void main(String[] args) throws IOException      {      System.out.print("Enter a word: ");    // get word      String input = getString();      size = input.length();                 // find its size      count = 0;      for(int j=0; j

3.递归的二分法查找

二分法查找效率高,因为它总是用最少的次数查到想要的值。

// binarySearch.java// demonstrates recursive binary search// to run this program: C>java BinarySearchAppclass ordArray   {   private long[] a;                 // ref to array a   private int nElems;               // number of data items   //-----------------------------------------------------------   public ordArray(int max)          // constructor      {      a = new long[max];             // create array      nElems = 0;      }   //-----------------------------------------------------------   public int size()      { return nElems; }   //-----------------------------------------------------------   public int find(long searchKey)      {      return recFind(searchKey, 0, nElems-1);      }   //-----------------------------------------------------------   private int recFind(long searchKey, int lowerBound,                                         int upperBound)      {      int curIn;      curIn = (lowerBound + upperBound ) / 2;      if(a[curIn]==searchKey)         return curIn;              // found it      else if(lowerBound > upperBound)         return nElems;             // can't find it      else                          // divide range         {         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()   //-----------------------------------------------------------   public void insert(long value)    // put element into array      {      int j;      for(j=0; j
value) // (linear search) break; for(int k=nElems; k>j; k--) // move bigger ones up a[k] = a[k-1]; a[j] = value; // insert it nElems++; // increment size } // end insert() //----------------------------------------------------------- public void display() // displays array contents { for(int j=0; j

4.汉诺塔问题(Hanoi)

这是个经典的游戏,下面的A、B、C分别代表左、中、右的三根柱子,1、2、3分别代表从上往下也就是从小到大的盘子。

// towers.java// solves Towers of Hanoi puzzle// to run this program: C>java TowersAppclass TowersApp   {   static int nDisks = 3;   public static void main(String[] args)      {      doTowers(nDisks, 'A', 'B', 'C');      }   //-----------------------------------------------------------   public static void doTowers(int topN,                               char src, char inter, char dest)      {      if(topN==1)         System.out.println("Disk 1 from " + src + " to "+ dest);      else         {         doTowers(topN-1, src, dest, inter);   // src to inter         System.out.println("Disk " + topN +   // move bottom                            " from " + src + " to "+ dest);         doTowers(topN-1, inter, src, dest);   // inter to dest         }      }//-------------------------------------------------------------   }  // end class TowersApp

5.归并排序

归并排序的效率要高于简单排序(冒泡、选择和插入排序),简单排序时间复杂度都是O(N2),而归并只需要O(N*logN),归并排序的一个缺点是它需要在存储器中有另一个大小等于被排序的数据项树木的数组,如果初始数组几乎占满整个存储器,那么归并排序将不能工作,但是如果有足够的空间,归并排序会是一个很好的选择。

下面是一个执行归并排序的java程序,它并不是递归程序,只是为了理解归并排序的插曲。

// merge.java// demonstrates merging two arrays into a third// to run this program: C>java MergeAppclass MergeApp   {   public static void main(String[] args)      {      int[] arrayA = {23, 47, 81, 95};      int[] arrayB = {7, 14, 39, 55, 62, 74};      int[] arrayC = new int[10];      merge(arrayA, 4, arrayB, 6, arrayC);      display(arrayC, 10);      }  // end main()   //-----------------------------------------------------------                                       // merge A and B into C     public static void merge( int[] arrayA, int sizeA,                               int[] arrayB, int sizeB,                               int[] arrayC )      {      int aDex=0, bDex=0, cDex=0;      while(aDex < sizeA && bDex < sizeB)  // neither array empty         if( arrayA[aDex] < arrayB[bDex] )            arrayC[cDex++] = arrayA[aDex++];         else            arrayC[cDex++] = arrayB[bDex++];      while(aDex < sizeA)                  // arrayB is empty,         arrayC[cDex++] = arrayA[aDex++];  // but arrayA isn't      while(bDex < sizeB)                  // arrayA is empty,         arrayC[cDex++] = arrayB[bDex++];  // but arrayB isn't      }  // end merge()   //-----------------------------------------------------------                                       // display array   public static void display(int[] theArray, int size)      {      for(int j=0; j

使用了递归的归并排序完整版。

// mergeSort.java// demonstrates recursive merge sort// to run this program: C>java MergeSortAppclass DArray   {   private long[] theArray;          // ref to array theArray   private int nElems;               // number of data items   //-----------------------------------------------------------   public DArray(int max)            // constructor      {      theArray = new long[max];      // create array      nElems = 0;      }   //-----------------------------------------------------------   public void insert(long value)    // put element into array      {      theArray[nElems] = value;      // insert it      nElems++;                      // increment size      }   //-----------------------------------------------------------   public void display()             // displays array contents      {      for(int j=0; j

6.消除递归

有一些算法趋向于用递归的方法,另一些则不是,其实递归的效率并不高,人们用他们只是他们更加简洁,所以有时候需要把递归的算法转换成非递归的,这种转换经常会用到栈。

事实上,大部分的编译器都是使用栈来实现递归的,当调用一个方法的时候,编译器会把这个方法的所有参数及返回地址(这个方法返回时控制到达的地方)都压入栈,然后把控制转移给这个方法,当这个方法返回的时候,这些值退栈,参数消失了,并且控制权重新回到返回地址处。

下面是一个转换的算法,实现的是前面的triangle.java,三角数字。

// stackTriangle.java// evaluates triangular numbers, stack replaces recursion// to run this program: C>java StackTriangleAppimport java.io.*;                 // for I/Oclass Params     // parameters to save on stack   {   public int n;   public int returnAddress;   public Params(int nn, int ra)      {      n=nn;      returnAddress=ra;      }   }  // end class Paramsclass StackX   {   private int maxSize;         // size of StackX array   private Params[] stackArray;   private int top;             // top of stack//--------------------------------------------------------------   public StackX(int s)         // constructor      {      maxSize = s;              // set array size      stackArray = new Params[maxSize];  // create array      top = -1;                 // no items yet      }//--------------------------------------------------------------   public void push(Params p)   // put item on top of stack      {      stackArray[++top] = p;    // increment top, insert item      }//--------------------------------------------------------------   public Params pop()          // take item from top of stack      {      return stackArray[top--]; // access item, decrement top      }//--------------------------------------------------------------   public Params peek()         // peek at top of stack      {      return stackArray[top];      }//--------------------------------------------------------------   }  // end class StackXclass StackTriangleApp   {   static int theNumber;   static int theAnswer;   static StackX theStack;   static int codePart;   static Params theseParams;//-------------------------------------------------------------   public static void main(String[] args) throws IOException      {      System.out.print("Enter a number: ");      theNumber = getInt();      recTriangle();      System.out.println("Triangle="+theAnswer);      }  // end main()//-------------------------------------------------------------   public static void recTriangle()      {      theStack = new StackX(10000);      codePart = 1;      while( step() == false)  // call step() until it's true         ;                     // null statement      }//-------------------------------------------------------------   public static boolean step()      {      switch(codePart)         {         case 1:                              // initial call            theseParams = new Params(theNumber, 6);            theStack.push(theseParams);            codePart = 2;            break;         case 2:                              // method entry            theseParams = theStack.peek();            if(theseParams.n == 1)            // test               {               theAnswer = 1;               codePart = 5;   // exit               }            else               codePart = 3;   // recursive call            break;         case 3:                              // method call            Params newParams = new Params(theseParams.n - 1, 4);            theStack.push(newParams);            codePart = 2;  // go enter method            break;         case 4:                              // calculation            theseParams = theStack.peek();            theAnswer = theAnswer + theseParams.n;            codePart = 5;            break;         case 5:                              // method exit            theseParams = theStack.peek();            codePart = theseParams.returnAddress; // (4 or 6)            theStack.pop();            break;         case 6:                              // return point            return true;         }  // end switch      return false;      }  // end triangle//-------------------------------------------------------------   public static String getString() throws IOException      {      InputStreamReader isr = new InputStreamReader(System.in);      BufferedReader br = new BufferedReader(isr);      String s = br.readLine();      return s;      }//-------------------------------------------------------------   public static int getInt() throws IOException      {      String s = getString();      return Integer.parseInt(s);      }//--------------------------------------------------------------   }  // end class StackTriangleApp

以上算法多少是系统的把一个递归程序转换成了使用栈的程序,这表明对于任意一个递归程序都有可能做出这种转换,然而在实践中,我们从一开始就不往递归想,所以一开始就用基于栈的方法,而不是从递归转换,这样就可以精简上面的程序,去掉了swith语句,使代码更有效率。

以下是更有效率的代码。

// stackTriangle2.java// evaluates triangular numbers, stack replaces recursion// to run this program: C>java StackTriangle2Appimport java.io.*;                 // for I/Oclass StackX   {   private int maxSize;        // size of stack array   private int[] stackArray;   private int top;            // top of stack//--------------------------------------------------------------   public StackX(int s)        // constructor      {      maxSize = s;      stackArray = new int[maxSize];      top = -1;      }//--------------------------------------------------------------   public void push(int p)     // put item on top of stack      { stackArray[++top] = p; }//--------------------------------------------------------------   public int pop()            // take item from top of stack      { return stackArray[top--]; }//--------------------------------------------------------------   public int peek()           // peek at top of stack      { return stackArray[top]; }//--------------------------------------------------------------   public boolean isEmpty()    // true if stack is empty      { return (top == -1); }//--------------------------------------------------------------   }  // end class StackXclass StackTriangle2App   {   static int theNumber;   static int theAnswer;   static StackX theStack;   public static void main(String[] args) throws IOException      {      System.out.print("Enter a number: ");      System.out.flush();      theNumber = getInt();      stackTriangle();      System.out.println("Triangle="+theAnswer);      }  // end main()//-------------------------------------------------------------   public static void stackTriangle()      {      theStack = new StackX(10000);    // make a stack      theAnswer = 0;                   // initialize answer      while(theNumber > 0)             // until n is 1,         {         theStack.push(theNumber);     // push value         --theNumber;                  // decrement value         }      while( !theStack.isEmpty() )     // until stack empty,         {         int newN = theStack.pop();    // pop value,         theAnswer += newN;            // add to answer         }      }//-------------------------------------------------------------   public static String getString() throws IOException      {      InputStreamReader isr = new InputStreamReader(System.in);      BufferedReader br = new BufferedReader(isr);      String s = br.readLine();      return s;      }//-------------------------------------------------------------   public static int getInt() throws IOException      {      String s = getString();      return Integer.parseInt(s);      }//--------------------------------------------------------------   }  // end class StackTriangle2App

总之,递归能简化代码,但是逻辑上比较复杂,效率也并不高。

转载于:https://my.oschina.net/liddhome/blog/825200

你可能感兴趣的文章
配置Tomcat及日志
查看>>
zabbix配置(上)
查看>>
2019年移动社交APP竞品前瞻性分析
查看>>
MySQL-MMM高可用
查看>>
安装 PrestaShop 1.6 - 关于快速安装指南
查看>>
杂谈 --- 出去走走,开拓视野。
查看>>
filebeat 接入kafka
查看>>
事情越多越需要一款适合的任务管理软件
查看>>
iOS使用[核心动画]和[定时器]两种方式实现【呼吸灯动画】(仿蘑菇街价格标签)...
查看>>
iOS基础问答面试题连载(二)
查看>>
无密码FTP登录
查看>>
网站和短信设备相结合如何办到
查看>>
使用 OpenGL 遇到的 Bug - 'color undeclared'
查看>>
C++编写的十进制转换成16进制源码
查看>>
如何对CAD绘图软件中的页面进行设置
查看>>
一致性hash算法及其java实现!
查看>>
大数据教程(3.7):zookeeper集群自动化启动、关闭、重启脚本
查看>>
大数据教程(6.4)centos6.9安装hadoop2.9.1
查看>>
awk基础简介
查看>>
我的友情链接
查看>>