一. 问题
给定一组数据,将元素用递归的手法打印出来。
二. 实例分析
1. 循环手法
给定一组数据, data = (1, 2, 3, 4, 5, 6)。现在要打印元素,常规手法就是用循环,代码如下:
1 void print_element(const vector<int>& data) { 2 for (auto &i : data) { 3 cout << i << " "; 4 } 5 }
只需要传入一个序列即可,不用别的参数(因为 vector 知道自己的大小)。
2. 递归手法
1 void print_element_recursive(const vector<int>& data, int n) { 2 if (n - 1 >= 0) { 3 print_element_recursive(data, n - 1); 4 } else { 5 return; 6 } 7 cout << data[n - 1] << " "; 8 9 }
在这个函数里,多了一个参数 n ,用于保存元素个数。如果用 data.size(),那么获取的大小始终都是固定值,就不能实现递归了。递归需要一个基准条件来结束,通过不断缩减传入的 n 值,就能够将序列逐步“压缩”至只有一个元素的情况(序列本身包含的元素没有变少,只是我们希望它在函数看来慢慢变少,这样最后只需要打印一个元素即可)。传入的 n 值是元素个数,与对应的下标相差 1 ,当 n = 1 时,表明只剩一个元素,此时下标应该为 0。不过这并不是最后一步。
n 最开始等于 6, 然后逐渐变化到 1 ,现在序列只包含一个元素,这个元素下标为 0。但是我们还需要再进一步,将 0 传入函数,此时 n - 1 = -1, 这是为了确认没有别的元素了。于是函数返回去,往下执行,到第 7 行代码,将该元素打印出来,打印完毕以后,函数继续返回,直到打印出所有元素。这是正序打印。如果需要逆序打印,只需要将第 3 行与第 7 行代码交换即可。
递归算法其实并不复杂,实现起来代码量也不大,关键在于如何放置递归语句。一定要理解,递归是层层深入,到达基准条件时,再层层返回,接着执行上次没执行完的剩余语句。