二叉树的遍历算法
一、算法原理
二叉树遍历是指按照特定的顺序访问树中所有节点的过程,主要分为深度优先遍历(DFS)和广度优先遍历(BFS)。深度优先遍历包括前序遍历、中序遍历和后序遍历,广度优先遍历即层次遍历。
二、 深度优先遍历(DFS)
1.前序遍历(Preorder Traversal)
访问顺序:根节点—>左子树–>右子数
特点:第一个访问的总是根节点。适用于复制树的结构、序列化、或作为前缀表达式(波兰表达式)
递归实现:
//递归实现
void preOrder(TreeNode* root){
if(nullptr == root) return;
cout<<root->val<<" "; //访问根节点
preOrder(root->left); //遍历左子树
preOrder(root->right); //遍历右子树
}
//迭代实现(使用栈)
//迭代思路:使用栈。先将根节点入栈。当栈不为空时,弹出栈顶节点并访问,然后先将其右子节点入栈,
//再将其左子节点入栈(栈是后进先出,以保证左子树先被处理)
void preOrderStack(TreeNode*root){
stack<TreeNode*> st;
if(root) st.push(root);
while(!st.empty()){
TreeNode* node = st.top();
st.pop();
cout<<node->val<<" ";
if(node->right) st.push(node->right);
if(node->left) st.push(node->left);
}
}
2.中序遍历(Inorder Traversal)
访问顺序:左子树->根节点->右子树
特点:二叉搜索树进行中序遍历,会得到一个升序序列。这是BST独有的重要性质,常用于排序和范围查询。
递归实现
void inorder(TreeNode* root){
if(nullptr == root) return;
inorder(root->left); //遍历左子树
cout<<root->val<<" ";//访问根节点
inorder(root->right); //遍历右子树
}
//迭代实现
//迭代思路:使用栈。用一个curr指针从根节点开始,沿左子树一直走到最底,并将路径上的节点全部入栈。
//然后弹出栈顶节点访问,并将curr指向该节点的右子节点,重复上述过程。
void inorderStack(TreeNode*root){
stack<TreeNode*> st;
TreeNode* curr = root;
while(curr || !st.empty()){
while(curr){
st.push(curr);
curr = curr->left; //左子树入栈
}
curr = st.top();
st.pop();
cout<<curr->val << " ";
curr = curr->right; //转向右子树
}
}
3.后序遍历(PostOrder Traversal)
访问顺序:左子树->右子树->根节点
特点:最后访问根节点。适用于先处理子节点再处理父节点的场景,如释放或删除树、计算目录大小、表达式求值(逆波兰表达式)
递归实现
//递归实现
void postOrder(TreeNode* root) {
if (root == nullptr) return;
postorder(root->left); // 遍历左子树
postorder(root->right); // 遍历右子树
cout << root->val << " "; // 访问根节点
}
//迭代实现
//迭代思路:使用栈。可以模拟“根->右->左”的顺序进行遍历(类似于变种的前序遍历),然后将结果逆序,
//即可得到“左->右->根”的后序结果。另一种经典方法是记录上一个访问的节点,以判断当前节点的右子树是否已被处理。
void postOrderStack(TreeNode* root){
stack<pair<TreeNode*,bool>>st;
st.push({root,false});
while(!st.empty()){
auto [node,visited] = st.top();
st.pop();
if(node) {
if(visited){
cout<<node->val<<" ";
}else{
st.push({node,true});
st.push({node->right,false});
st.push({node->left,false});
}
}
}
}
}
三、广度优先遍历(BFS)
层次遍历(Level Order Traversal)
按层访问节点,使用队列实现
void levelOrder(TreeNode * root){
queue<TreeNode*>q;
if(root) q.push(root);
while(!q.empty()){
TreeNode* node= q.front();
q.pop();
cout<<node->val << " ";
if(node->left) q.push(node->left);
if(node->right) q.push(node->root);
}
}
四、应用场景
- 前序遍历:复制树结构、表达式树的前缀表示
- 中序遍历:二叉搜索树的有序输出
- 后序遍历:释放数内存、表达式数的后缀计算
- 层次遍历:查找树的高度、层序构件二叉树
五、时间复杂度和空间复杂度
时间复杂度:O(n)(n为节点数)
空间复杂度:递归实现为:O(h)(h为树高), 迭代实现方式 :O(n)
六、调用示例
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int v):val(v),left(nullptr),right(nullptr){}
};
TreeNode* buildTree(vector<int>&nums) {
if (nums.empty()) return nullptr;
queue<TreeNode*> q;
TreeNode* root = new TreeNode(nums[0]);
q.push(root);
int i = 1;
while (!q.empty() && i<nums.size()) {
TreeNode* node = q.front();
q.pop();
//处理左子节点
if (i < nums.size()) {
node->left = new TreeNode(nums[i]);
q.push(node->left);
}
++i;
//处理右子树节点
if (i < nums.size()) {
node->right = new TreeNode(nums[i]);
q.push(node->right);
}
++i;
}
return root;
}
void freeTree(TreeNode*root) {
if (nullptr == root) return;
freeTree(root->left);
freeTree(root->right);
if (root) {
cout << "free node:" << root->val << " ";
delete root;
root = nullptr;
}
}
void tree_seach_test() {
//构造树
vector<int> treeNode = { 1,2,3,4,5,6,7 };
TreeNode* root = buildTree(treeNode);
//前序遍历算法
cout << "preOrder Start:";
preOrder(root);
cout << endl;
cout << "preOrderStack Start:";
preOrderStack(root);
cout << endl;
//中序遍历算法
cout << "inOrder Start:";
inOrder(root);
cout << endl;
cout << "inOrderStack Start:";
inOrderStack(root);
cout << endl;
//后序遍历算法
cout << "postOrder Start:";
postOrder(root);
cout << endl;
cout << "postOrderStack Start:";
postOrderStack(root);
cout << endl;
//广度优先算法
cout << "BFS Start:";
levelOrder(root);
cout << endl;
//释放树空间
freeTree(root);
}
int main(){
cout << "Tree Search Start:" << endl;
tree_seach_test();
cout << endl;
getchar();
}

4532

被折叠的 条评论
为什么被折叠?



