算法Sedgewick第四版-第1章基础-001递归

一、

方法可以调用自己(如果你对递归概念感到奇怪,请完成练习 1.1.16 到练习 1.1.22)。例如,
下面给出了 BinarySearch 的 rank() 方法的另一种实现。我们会经常使用递归,因为递归代码比
相应的非递归代码更加简洁优雅、易懂。下面这种实现中的注释就言简意赅地说明了代码的作用。
我们可以用数学归纳法证明这段注释所解释的算法的正确性。我们会在 3.1 节中展开这个话题并为
二分查找提供一个这样的证明。
编写递归代码时最重要的有以下三点。
‰ 递归总有一个最简单的情况——方法的第一条语句总是一个包含 return 的条件语句。
‰ 递归调用总是去尝试解决一个规模更小的子问题,这样递归才能收敛到最简单的情况。在下
面的代码中,第四个参数和第三个参数的差值一直在缩小。

递归调用的父问题和尝试解决的子问题之间不应该有交集。在下面的代码中,两个子问题各
自操作的数组部分是不同的。

1 public static int rank(int key, int[] a, int lo, int hi) { 
2     //如果key存在于a[]中,它的索引不会小于lo且不会大于hi
3     if (lo > hi) return -1;
4     int mid = lo + (hi - lo) / 2;
5     if (key < a[mid]) return rank(key, a, lo, mid - 1);
6     else if (key > a[mid]) return rank(key, a, mid + 1, hi);
7     else return mid;
8 }

非递归算法

 

 1     /**
 2      * Returns the index of the specified key in the specified array.
 3      *
 4      * @param  a the array of integers, must be sorted in ascending order
 5      * @param  key the search key
 6      * @return index of key in array <tt>a</tt> if present; <tt>-1</tt> otherwise
 7      */
 8     public static int indexOf(int[] a, int key) {
 9         // 数组必须是有序的
10         int lo = 0;
11         int hi = a.length - 1;
12         while (lo <= hi) {
13             // Key is in a[lo..hi] or not present.
14             int mid = lo + (hi - lo) / 2;
15             if      (key < a[mid]) hi = mid - 1;
16             else if (key > a[mid]) lo = mid + 1;
17             else return mid;
18         }
19         return -1;
20     }

 

 

 

违背其中任意一条都可能得到错误的结果或是低效的代码(见练习 1.1.19 和练习 1.1.27),而

坚持这些原则能写出清晰、正确且容易评估性能的程序。使用递归的另一个原因是我们可以使用数
学模型的来估计程序的性能。我们会在 3.2 节的二分查找以及其他几个地方分析这个问题。

posted @ 2016-03-10 23:07  shamgod  阅读(405)  评论(0编辑  收藏  举报
haha