建议31:使用迭代
任何可以用递归实现的算法都可以用迭代实现。迭代算法通常包括几个不同的循环,分别对应算法过程的不同方面。虽然迭代也会导致性能问题,但是使用优化的循环替代长时间运行的递归函数可以提高性能,因为运行一个循环比反复调用一个函数的开销要低。
例如,合并排序算法是最常用的以递归实现的算法。下面是一个简单的合并排序算法:
- function merge(left, right) {
- var result = [];
- while(left.length > 0 && right.length > 0) {
- if(left[0] < right[0]) {
- result.push(left.shift());
- } else {
- result.push(right.shift());
- }
- }
- return result.concat(left).concat(right);
- }
- function mergeSort(items) {
- if(items.length == 1) {
- return items;
- }
- var middle = Math.floor(items.length / 2), left = items.slice(0, middle), right = items.slice(middle);
- return merge(mergeSort(left), mergeSort(right));
- }
这个合并排序代码相当简单直接,其中mergeSort()函数被调用得非常频繁。对一个超过1500项的数组进行操作,就可能在Firefox 上导致栈溢出。程序陷入栈溢出错误并不一定要修改整个算法,这说明递归不是最好的实现方法。合并排序算法还可以用迭代实现,例如: - function mergeSort(items) {
- if(items.length == 1) {
- return items;
- }
- var work = [];
- for(var i = 0, len = items.length; i < len; i++) {
- work.push([items[i]]);
- }
- work.push([]);
- for(var lim = len; lim > 1; lim = (lim + 1) / 2) {
- for(var j = 0, k = 0; k < lim; j++, k += 2) {
- work[j] = merge(work[k], work[k + 1]);
- }
- work[j] = [];
- }
- return work[0];
- }
在上面代码中,mergeSort()实现与上一个 merge函数同样的功能却没有使用递归。虽然迭代可能比递归合并排序慢一些,但是它不会像递归那样影响调用栈。将递归算法切换为迭代是避免栈溢出错误的方法之一。
时间: 2024-09-30 04:54:44