二叉树的递归与非递归遍历实现

参阅资料:http://blog.csdn.net/ns_code/article/details/12977901
二叉树是很常见的数据结构, 它的遍历方式有递归和非递归两种,其中递归方式易于实现,而非递归的方式往往效率更高,耗资源更少,各有千秋,下面就来介绍下具体的实现方法。

节点结构:

typedef struct Node{
    int val;
    Node* left;
    Node* right;
    Node(int val) : val(val), left(NULL), right(NULL) {}
} *pNode;

先序遍历:

递归方式:
首先遍历其根结点,然后遍历左子树,最后遍历右子树,对于其子树的遍历方式同上。

void BST::Recursion_preOrder_Traverse(pNode node){
    if(node){
        printf("%d ", node->val);
        Recursion_preOrder_Traverse(node->left);
        Recursion_preOrder_Traverse(node->right);
    }
}

非递归方式:
无非就是模拟递归,这里我们用栈模拟。
首先设置一个当前指针curNode,用于指向当前需要操作的节点。
1:对于一个节点,我们输出它的值,将其入栈,并判断左子树是否为空
2:如果不为空,那么curNode指向它,重复1
3:如果为空,说明此时左子树已经遍历完毕,并令当前节点出栈,因为已经遍历过了,令curNode指向当前节点的右节点,判断curNode是否为空。
4:如果不为空,重复1
5:如果为空,说明其没有右子树,继续出栈,重复4、5
6:如果当前curNode为空并且栈为空,则遍历完毕。

void BST::Non_Recursion_preOrder_Traverse(pNode root){
    stack<pNode> pNode_stack;
    pNode curNode = root;
    while(curNode != NULL || !pNode_stack.empty()){
        printf("%d ", curNode->val);
        pNode_stack.push(curNode);
        curNode = curNode->left;
        while(!curNode && !pNode_stack.empty()){//当指针为空并且栈内有元素时,就可以取出来遍历右子树了
            curNode = pNode_stack.top();
            pNode_stack.pop();
            curNode = curNode->right;
        }
    }
}

中序遍历:

递归方式:
首先遍历其左子树,然后输出自己的值,最后遍历右子树,对于其子树的遍历方式同上。

void BST::Recursion_inOrder_Traverse(pNode node){
    if(node){
        Recursion_inOrder_Traverse(node->left);
        printf("%d ", node->val);
        Recursion_inOrder_Traverse(node->right);
    }
}

非递归方式:
1:若当前节点左子树不为空,则将该节点入栈,重复1
2:若当前节点左子树为空,则输出其值(注意这里并没有将该节点入栈),curNode指向它的右子树,判断是否为空
3:若不为空,则重复1、2
4:若为空,则将栈顶元素取出,输出其值,curNode指向它的右子树,判断其是否为空,重复3、4
5:如果当前curNode为空并且栈为空,则遍历完毕。

void BST::Non_Recursion_inOrder_Traverse(pNode root){
    stack<pNode> pNode_stack;
    pNode curNode = root;
    while(curNode != NULL || !pNode_stack.empty()){
        if(curNode->left != NULL){
            pNode_stack.push(curNode);
            curNode = curNode->left;
        }
        else{
            printf("%d ", curNode->val);
            curNode = curNode->right;
            while(!curNode && !pNode_stack.empty()){
                //此时curNode的左子树全部遍历完毕,输出自己
                curNode = pNode_stack.top();
                printf("%d ", curNode->val);
                pNode_stack.pop();
                curNode = curNode->right;
            }
        }
    }
}

后序遍历:

递归方式:
首先遍历左子树,然后遍历右子树,最后输出自己,对于其子树的遍历方式同上。

void BST::Recursion_postOrder_Traverse(pNode node){
    if(node){
        Recursion_postOrder_Traverse(node->left);
        Recursion_postOrder_Traverse(node->right);
        printf("%d ", node->val);
    }
}

非递归方式:
这里要多加一个记录上一个访问节点的preNode
1:首先将节点入栈
2:如果单签节点是叶子节点或者它的左右孩子已经有输出的了,则将其直接输出并出栈,将栈顶节点设为curNode并将出栈节点设为preNode
3:若2不满足,则将该节点的右孩子和左孩子依次入栈,重复2
4:若栈为空,则遍历结束。

void BST::Non_Recursion_postOrder_Traverse(pNode root){
    stack<pNode> pNode_stack;
    pNode curNode = root;
    pNode preNode = NULL;
    pNode_stack.push(curNode);
    while(!pNode_stack.empty()){
        curNode = pNode_stack.top();
        if((curNode->left == NULL && curNode->right == NULL) ||
            (preNode != NULL && (curNode->left == preNode || curNode->right == preNode))){
            printf("%d ", curNode->val);
            pNode_stack.pop();
            preNode = curNode;
        }
        else{
            if(curNode->right != NULL)
                pNode_stack.push(curNode->right);
            if(curNode->left != NULL)
                pNode_stack.push(curNode->left);
        }
    }
}

程序总览:

#include <cstdio>
#include <stack>
using namespace std;

typedef struct Node{
    int val;
    Node* left;
    Node* right;
    Node(int val) : val(val), left(NULL), right(NULL) {}
} *pNode;

class BST{
private:
    pNode root;

    void Non_Recursion_Insert_Node(pNode *root, int x);
    void Non_Recursion_postOrder_Traverse(pNode root);
    void Recursion_postOrder_Traverse(pNode node);
    void Non_Recursion_inOrder_Traverse(pNode root);
    void Recursion_inOrder_Traverse(pNode root);
    void Recursion_Delete_BST(pNode node);
    void Non_Recursion_preOrder_Traverse(pNode root);
    void Recursion_preOrder_Traverse(pNode node);
public:
    void Non_Recursion_Insert_Node(int x);
    void Non_Recursion_postOrder_Traverse();
    void Recursion_postOrder_Traverse();
    void Non_Recursion_inOrder_Traverse();
    void Recursion_inOrder_Traverse();
    void Non_Recursion_preOrder_Traverse();
    void Recursion_preOrder_Traverse();
    void Build_BST(int *num, int n);
    BST();
    ~BST();
};

void BST::Build_BST(int *num, int n){
    for(int i = 0; i < n; i++){
        Non_Recursion_Insert_Node(&this->root, num[i]);
    }
}

void BST::Non_Recursion_Insert_Node(int x){
    Non_Recursion_Insert_Node(&this->root, x);
}

void BST::Non_Recursion_Insert_Node(pNode *root, int x){
    pNode child = *root;
    pNode parent = NULL;
    while(child != NULL){
        parent = child;
        if(child->val > x){
            child = child->left;
        }
        else{
            child = child->right;
        }
    }
    if(parent == NULL){
        *root = new Node(x);
    }
    else if(parent->val > x){
        parent->left = new Node(x);
    }
    else{
        parent->right = new Node(x);
    }
}

void BST::Non_Recursion_preOrder_Traverse(){
    Non_Recursion_preOrder_Traverse(this->root);
}

void BST::Non_Recursion_preOrder_Traverse(pNode root){
    stack<pNode> pNode_stack;
    pNode curNode = root;
    while(curNode != NULL || !pNode_stack.empty()){
        printf("%d ", curNode->val);
        pNode_stack.push(curNode);
        curNode = curNode->left;
        while(!curNode && !pNode_stack.empty()){//当指针为空并且栈内有元素时,就可以取出来遍历右子树了
            curNode = pNode_stack.top();
            pNode_stack.pop();
            curNode = curNode->right;
        }
    }
}

void BST::Recursion_preOrder_Traverse(pNode node){
    if(node){
        printf("%d ", node->val);
        Recursion_preOrder_Traverse(node->left);
        Recursion_preOrder_Traverse(node->right);
    }
}

void BST::Recursion_preOrder_Traverse(){
    Recursion_preOrder_Traverse(this->root);
}

void BST::Non_Recursion_inOrder_Traverse(){
    Non_Recursion_inOrder_Traverse(this->root);
}

void BST::Non_Recursion_inOrder_Traverse(pNode root){
    stack<pNode> pNode_stack;
    pNode curNode = root;
    while(curNode != NULL || !pNode_stack.empty()){
        if(curNode->left != NULL){
            pNode_stack.push(curNode);
            curNode = curNode->left;
        }
        else{
            printf("%d ", curNode->val);
            curNode = curNode->right;
            while(!curNode && !pNode_stack.empty()){
                //此时curNode的左子树全部遍历完毕,输出自己
                curNode = pNode_stack.top();
                printf("%d ", curNode->val);
                pNode_stack.pop();
                curNode = curNode->right;
            }
        }
    }
}

void BST::Recursion_inOrder_Traverse(pNode node){
    if(node){
        Recursion_inOrder_Traverse(node->left);
        printf("%d ", node->val);
        Recursion_inOrder_Traverse(node->right);
    }
}

void BST::Recursion_inOrder_Traverse(){
    Recursion_inOrder_Traverse(this->root);
}

void BST::Non_Recursion_postOrder_Traverse(){
    Non_Recursion_postOrder_Traverse(this->root);
}

void BST::Non_Recursion_postOrder_Traverse(pNode root){
    stack<pNode> pNode_stack;
    pNode curNode = root;
    pNode preNode = NULL;
    pNode_stack.push(curNode);
    while(!pNode_stack.empty()){
        curNode = pNode_stack.top();
        if((curNode->left == NULL && curNode->right == NULL) ||
            (preNode != NULL && (curNode->left == preNode || curNode->right == preNode))){
            //如果当前节点为叶子节点或者它的子节点有已经输出的 那么就输出这个节点
            //为什么任意左右节点只要有输出的,该节点就会输出呢?这是因为底下的else决定的
            //访问该节点之前一定会访问它的左右子节点,如果preNode保存的是它的左节点,那么
            //一定不存在右节点,当然下一个会访问他自己,如果perNode保存的是右节点,则说明
            //左节点已经被访问完毕,这是由入栈顺序决定的。
            printf("%d ", curNode->val);
            pNode_stack.pop();
            preNode = curNode;
        }
        else{
            if(curNode->right != NULL)
                pNode_stack.push(curNode->right);
            if(curNode->left != NULL)
                pNode_stack.push(curNode->left);
        }
    }
}

void BST::Recursion_postOrder_Traverse(pNode node){
    if(node){
        Recursion_postOrder_Traverse(node->left);
        Recursion_postOrder_Traverse(node->right);
        printf("%d ", node->val);
    }
}

void BST::Recursion_postOrder_Traverse(){
    Recursion_postOrder_Traverse(this->root);
}

void BST::Recursion_Delete_BST(pNode node){
    if(node == NULL)
        return;
    if(node->left != NULL)
        Recursion_Delete_BST(node->left);
    if(node->right != NULL)
        Recursion_Delete_BST(node->right);
    delete node;
}

BST::BST(){
    root = NULL;
}

BST::~BST(){
    Recursion_Delete_BST(this->root);
}

int main()
{
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值