准备
深度优先遍历:沿着每一个分支路径进行深入访问。前序、中序、后序都是深度优先遍历的特例。可以用递归实现,非递归一般借助栈容器。
广度优先遍历:又叫层次遍历,对每一层依次访问。可以借助队列容器来实现。
先定义和创建一颗二叉树
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
//定义二叉树结点
template<typename T>
struct Node
{
T value;
Node<T> *left;
Node<T> *right;
Node(const T &val)
:value(val), left(nullptr), right(nullptr)
{}
Node(const T &val, Node<T> *&lnode, Node<T> *&rnode)
:value(val), left(lnode), right(rnode)
{}
};
//创建二叉树
template<typename T>
Node<T>* createBinaryTree(const std::initializer_list<T> &list)
{
std::vector<Node<T>*> vec;
for (auto &item : list)
{
Node<T> *newNode = new Node<T>(item);
vec.push_back(newNode);
}
for (std::size_t i = 0; i < vec.size(); i++)
{
if (i * 2 + 1 < vec.size())
vec[i]->left = vec[i * 2 + 1];
if (i * 2 + 2 < vec.size())
vec[i]->right = vec[i * 2 + 2];
}
return vec[0];
}
//删除二叉树
template<typename T>
void deleteBinaryTree(Node<T> *&rootNode)
{
if (!rootNode)
return;
deleteBinaryTree(rootNode->left);
deleteBinaryTree(rootNode->right);
delete rootNode;
rootNode = nullptr;
}
int main()
{
Node<int> *test = createBinaryTree({ 1, 2, 3, 4, 5, 6, 7 ,8,9 });//创建
preorder(test);//前序--递归
std::cout << endl;
preorder2(test);//前序--非递归
std::cout << endl;
inorder(test);//中序--递归
std::cout << endl;
inorder2(test);//中序--非递归
std::cout << endl;
postorder(test);//后续--递归
std::cout << endl;
postorder2(test);//后续--非递归
std::cout << endl;
breadthFirst(test);//层次
std::cout << endl;
deleteBinaryTree(test);//释放
system("pause");
return 0;
}
前序遍历
前序遍历先访问根节点,再访问左右子树。
//前序遍历 --递归
template<typename T>
void preorder(Node<T> *&rootNode)
{
if (!rootNode)
return;
//根->左->右
std::cout << rootNode->value << " ";
preorder(rootNode->left);
preorder(rootNode->right);
}
//前序遍历 --栈
template<typename T>
void preorder2(Node<T> *&rootNode)
{
std::stack<Node<T>*> nodeStack;
Node<T> *tempNode = rootNode;
while (!nodeStack.empty() || tempNode)
{
if (tempNode) {
std::cout << tempNode->value<<" ";
nodeStack.push(tempNode);
tempNode = tempNode->left;//根->左
}
else {
tempNode = nodeStack.top();
nodeStack.pop();
tempNode = tempNode->right;//右
}
}
}
中序遍历
中序遍历,访问根节点的次序在其左右子树之间。
//中序遍历 --递归
template<typename T>
void inorder(Node<T> *&rootNode)
{
if (!rootNode)
return;
//左->根->右
inorder(rootNode->left);
std::cout << rootNode->value << " ";
inorder(rootNode->right);
}
//中序遍历 --栈
template<typename T>
void inorder2(Node<T> *&rootNode)
{
std::stack<Node<T>*> nodeStack;
Node<T> *tempNode = rootNode;
while (!nodeStack.empty() || tempNode)
{
if (tempNode) {
nodeStack.push(tempNode);
tempNode = tempNode->left;//左
}
else {
tempNode = nodeStack.top();
nodeStack.pop();
std::cout << tempNode->value << " ";
tempNode = tempNode->right;//根->右
}
}
}
后序遍历
后序遍历先访问左右子树,最后才访问根节点 。
//后序遍历 --递归
template<typename T>
void postorder(Node<T> *&rootNode)
{
if (!rootNode)
return;
//左->右->根
postorder(rootNode->left);
postorder(rootNode->right);
std::cout << rootNode->value << " ";
}
//后序遍历 --栈
template<typename T>
void postorder2(Node<T> *&rootNode)
{
std::stack<Node<T>*> nodeStack;
Node<T> *curNode = rootNode; //当前节点
Node<T> *preNode = nullptr; //之前访问过的节点,用来存
//把cur移动到左子树最下边
while (curNode)
{
nodeStack.push(curNode);
curNode = curNode->left;
}
while (!nodeStack.empty())
{
//走到这里,cur空,并已经遍历到左子树底端
curNode = nodeStack.top();
nodeStack.pop();
//无右或右已访问才访问根节点
if (!curNode->right || curNode->right == preNode){
std::cout << curNode->value << " ";
preNode = curNode;
}
//右子树未访问
else{
//根节点再次入栈
nodeStack.push(curNode);
//进入右子树
curNode = curNode->right;
//把cur移动到右子树的左子树最下边
while (curNode)
{
nodeStack.push(curNode);
curNode = curNode->left;
}
}
}
}
层次遍历
层次遍历从上到下一层一层的遍历。
用队列的话,每访问一层,都把左右子树入栈,相当于把下一层入栈。出栈时,顺序也就是一层一层的了。
//广度优先 --队列
template<typename T>
void breadthFirst(Node<T> *&rootNode)
{
if (!rootNode)
return;
std::queue<Node<T>*> nodeQueue;
Node<T> *tempNode = nullptr;
nodeQueue.push(rootNode);
while (!nodeQueue.empty())
{
tempNode = nodeQueue.front();
std::cout << tempNode->value << " ";
nodeQueue.pop();
if (tempNode->left)
nodeQueue.push(tempNode->left);
if (tempNode->right)
nodeQueue.push(tempNode->right);
}
}
参考
博客:https://blog.csdn.net/z_ryan/article/details/80854233
博客:https://blog.csdn.net/qq_40772692/article/details/79343914
来源:CSDN
作者:龚建波
链接:https://blog.csdn.net/gongjianbo1992/article/details/88378805