将条件递归算法转换为迭代算法
Turn conditional recursion algorithm to an iterative one
最近我写了一个基于递归的算法来水平打印二叉树。一般来说,我将基于递归的算法转换为基于迭代的算法没有任何问题,但我只是不知道如何做到这一点。
说我们是一个向量
std::vector<int> tree = {10,9,8,7,6,5,4};
它表示以下树:
10
/
9 8
/ /
7 6 5 4
我的算法通过采用以下路线来工作:
index -> left -> left Or in our case 10 -> 9 -> 7
-> right -> 6
-> right -> left -> 8 -> 5
-> right -> 4
等,并根据树的大小进行扩展。我无法理解的是,当我有条件地使用递归时,如何将代码转换为 while 循环。我不擅长解释,所以这里是代码。
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <unistd.h>
/* The Padding function handles the spacing and the vertical lines whenever we print a *
* right child. This depends on the previous parent-child hierarchy of the child *
* Printer handles the work of printing the elements and uses a depth-first-search *
* algorithm as it's core. Left children are printed horizontally while the right ones *
* are printed vertically. Print_tree is a wrapper. It also finds the max-length value *
* which will be used for formatting so that the formatting won't get messed up because *
* of the different number of digits. */
std::string do_padding (unsigned index, unsigned mlength){
std::string padding;
while(int((index-1)/2) != 0){
padding = (int((index-1)/2) % 2 == 0) ?
std::string(mlength+4,' ') + " " + padding :
std::string(mlength+3,' ') + "| " + padding ;
index = int((index-1)/2);
}
return padding;
}
template <class T>
void printer (std::vector<T> const & tree, unsigned index, unsigned mlength){
auto last = tree.size() - 1 ;
auto left = 2 * index + 1 ;
auto right = 2 * index + 2 ;
std::cout << " " << tree[index] << " " ;
if (left <= last){
auto llength = std::to_string(tree[left]).size();
std::cout << "---" << std::string(mlength - llength,'-');
printer(tree,left,mlength);
if (right <= last) {
auto rlength = std::to_string(tree[right]).size();
std::cout << std::endl<< do_padding(right,mlength) << std::string(mlength+ 3,' ') << "| " ;
std::cout << std::endl << do_padding(right,mlength) << std::string(mlength+ 3,' ') << "└─" <<
std::string(mlength - rlength,'-');
printer(tree,right,mlength);
}
}
}
template <class T>
void print_tree (std::vector<T> & tree){
unsigned mlength = 0;
for (T & element : tree){
auto length = std::to_string(element).size();
if (length > mlength) {
mlength = length;
}
}
std::cout << std::fixed << std::string(mlength- std::to_string(tree[0]).size(),' ') ;
printer(tree,0,mlength);
}
int main() {
std::vector<int> test;
for (auto i =0; i != 200; ++i) {
test.push_back(rand() % 12200);
}
std::make_heap(test.begin(),test.end());
std::cout << std::endl << "Press ENTER to show heap tree.." << std::endl;
std::cin.ignore();
print_tree(test);
std::cout << std::endl;
}
可能不值得重写,但我想知道如何处理这样的递归,以防将来我必须做类似的事情。
我
记得,您发布了树格式的打印堆数组问题。所以,对我来说(没有阅读代码),树遍历的核心算法是DFS。
要使此递归算法迭代,您可以做的是使用堆栈。堆栈基本上包含所有访问过的节点,并能够走回它所走的路径。迭代DFS与递归DFS和不同的元素顺序给出了一个例子。
对于大多数遍历树的算法,如果要以非递归方式表述它们,则需要额外的数据结构。对于深度优先遍历(如您的情况),您通常会使用堆栈(对于广度优先遍历,使用队列......
在伪代码中,打印树看起来像
function print_tree(tree_vector)
s = new stack<int>()
s.push(0)
while (!s.empty())
index = s.pop()
print (tree_vector[index])
left = 2*index + 1
right = 2*index + 2
if (right < tree_vector.size())
s.push(right)
if (left < tree_vector.size())
s.push(left)
end while
end function
请注意,此堆栈隐式表示编译器在进行递归调用时内部使用的调用堆栈。
相关文章:
- 如何为指向复杂值的迭代器专门化算法?
- 为什么范围算法与 std 的迭代器不兼容?
- 使用 Rcpp 加速替换迭代算法中的列表和向量元素是否合法?
- 使用迭代深度优先搜索算法的未加权图的最短路径
- 当迭代器(输入参数)通常不是constexpr时,constexpr算法真的有用吗
- 迭代算法之前的高效内存分配
- 迭代快速排序方法的分区算法问题
- 在 stl 算法中移动迭代器
- 迭代卡拉苏巴算法在C++中使用OpenACC并行化和矢量化
- 指针算法是否适用于迭代器?
- 用于双向迭代器的高德纳-莫里斯-普拉特算法
- 从递归算法到迭代算法
- 迭代算法的时间复杂度
- 在目标函数中使用迭代器的 STL 算法
- 将条件递归算法转换为迭代算法
- stl风格的算法:如何管理输出迭代器
- 为什么C++ STL 中算法、迭代器和容器是分开的
- 有一个标准的算法可以在一个范围内迭代吗
- C++前向迭代器算法
- 如何从递归算法转换为迭代算法