c++的标准模板库中并不提供专门的二叉树模板 ,为了实现二叉搜索树的深度优先和广度优先遍历的操作,我们可以自定义一个简单的二叉树:
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
class treenode {
public:
int val;
treenode* left;
treenode* right;
treenode(int value) :val(value), left(nullptr), right(nullptr) {}
};
class binarytree {
private:
treenode* root;
public:
binarytree() :root(nullptr) {}
void insert(treenode* node_val, treenode* node_pos = nullptr) {
if (root == nullptr) {
root = node_val;
cout << "根节点设置成功" << endl;
return;
}
if (node_pos == nullptr) {
cout << "没有指定节点插入的位置" << endl;
return;
}
if (node_val->val < node_pos->val && node_pos->left == nullptr) {
node_pos->left = node_val;
cout << "向左插入节点成功" << endl;
return;
}
if (node_val->val >= node_pos->val && node_pos->right == nullptr) {
node_pos->right = node_val;
cout << "向右插入节点成功" << endl;
return;
}
}
};
int main() {
treenode n1(11);
treenode n2(3);
treenode n3(55);
treenode n4(22);
treenode n5(1);
binarytree t;
t.insert(&n1);
t.insert(&n2,&n1);
t.insert(&n3, &n1);
t.insert(&n4, &n2);
t.insert(&n5, &n2);
}
我们所构建的这个简单二叉树是这样的:
11
/ \
3 55
/ \
1 22
DFS(深度优先遍历):
在二叉树的深度优先遍历中,搜索“深入”树中尽可能远的节点,直到到达一个叶子节点,然后回溯到之前的节点以探索其他路径。这种方法倾向于首先完全访问一个节点的子树,然后再移动到同一级别的下一个节点。DFS又分为前序遍历,中序遍历,后序遍历,它们的区别是:
1.前序遍历:首先访问当前节点,然后是左子树,最后是右子树。
2.中序遍历:首先访问左子树,然后是当前节点,最后是右子树。
3.后续遍历:首先访问右子树,然后是当前节点,最后是左子树。
我们可以使用栈或递归的方式来实现DFS操作;
1.前序遍历(递归):
void pre_order(treenode* node) {
if (node == nullptr) { //设置递归终止条件
return;
}
cout << node->val << " "; //打印此节点的数据值
pre_order(node->left); //递归访问左子树
pre_order(node->right); //递归访问右子树
}
前序遍历(栈):
void DFS_stack(treenode* node) {
stack<treenode*> stack; //使用c++标准模板库创建一个用于存储节点的栈
stack.push(node); //将当前节点加入栈中
while (!stack.empty()) { //当栈不为空,进行循环
treenode* temp = stack.top(); //获取栈的头部元素
stack.pop(); //弹出栈顶元素
cout << temp->val<<" "; //打印栈顶元素值
if (temp->right) { //如果栈顶元素的右节点存在
stack.push(temp->right); //栈中加入此元素
}
if (temp->left) { //如果栈顶元素的左节点存在
stack.push(temp->left); //栈中加入此元素
}
}
}
2.中序遍历:(递归)
void in_order(treenode* node) {
if (node == nullptr) {
return;
}
in_order(node->left);
cout << node->val << " ";
in_order(node->right);
}
3.后续遍历:(递归)
void post_order(treenode* node) {
if (node == nullptr) {
return;
}
post_order(node->left);
post_order(node->right);
cout << node->val << " ";
}
BFS(广度优先遍历):
在二叉树的广度优先遍历中,搜索是逐层进行的,从根节点开始,首先访问所有第一级的节点,然后是所有第二级的节点,依此类推。这种方法首先完全访问当前级别的所有节点,然后再移动到下一个级别。广度优先遍历通常使用队列来跟踪待访问的节点。
广度优先遍历的特点是它优先访问离根节点更近的节点。这种方式特别适用于搜索最短路径或者是在树中层级较浅的节点。
广度优先遍历(队列实现):
void BFS(treenode* node) {
queue<treenode*> queue; //创建一个存储二叉树节点的队列
queue.push(node); //将此节点加入队列
while (!queue.empty()) { //如果队列不为空,进入循环
treenode* temp = queue.front(); //获取队首元素
queue.pop(); //弹出队首元素
cout << temp->val; //打印队首元素值
if (temp->left) { //如果队首元素的左节点存在
queue.push(temp->left); //将此节点加入队列
}
if (temp->right) { //如果队首元素右节点存在
queue.push(temp->right); //将此节点加入队列
}
}
}