树的遍历

数的遍历有4种,分别是前序遍历,中序遍历和后序遍历、层次遍历。
前序遍历:根左右
中序遍历:左根右
后序遍历:左右根
层次遍历:第一层节点从左到右,第二层节点从左到右,以此类推。
分享下我怎么记忆的,只需要记得第一个字表示根的位置,就不会搞混了。另外还要知道,如果只知道前序和后序,是不能唯一确定一棵树的。

对于每种遍历,又存在递归式和非递归式。递归式当然好实现,只要简单的几行代码就可以实现;而非递归式呢,需要花点功夫,另外非递归式的后序遍历还有点小麻烦。下面来直接看代码吧

树的结构体

struct BinaryTreeNode{
    int value;
    BinaryTreeNode *pLeft;
    BinaryTreeNode *pRight;
};

递归式

递归式前序遍历

void preOrder(BinaryTreeNode* root){
    if(root==NULL){
        return ;
    }
    else{
        cout<<root->value;
        preOrder(root->pLeft);
        preOrder(root->pRight);     
    }   
}

递归式中序遍历

void InOrder(BinaryTreeNode* root){
    if(root==NULL){
        return ;
    }
    else{
        InOrder(root->pLeft);
        cout<<root->value;
        InOrder(root->pRight);      
    }

}

递归式后序遍历

void postOrder(BinaryTreeNode* root){
    if(root==NULL){
        return ;
    }
    else{
        postOrder(root->pLeft);
        postOrder(root->pRight);    
        cout<<root->value;  
    }   
}

总结:可以看到,我们只需要短短的几行代码就可以实现。只需要记住前序遍历、中序遍历和后序遍历的遍历方式即可。


非递归式

非递归式前序遍历

void PreOrder1(BinaryTreeNode* root){
    if (root==NULL){
        return;
    }
    BinaryTreeNode *node = root;
    stack<BinaryTreeNode*>nodelist;
    while(!nodelist.empty()||node!=NULL){
        while(node!=NULL){
            nodelist.push(node);
            cout<<node->value;
            node = node->pLeft;
        }   
        node = nodelist.top();
        nodelist.pop();
        node = node->pRight;
    }
}

非递归式中序遍历

void InOrder1(BinaryTreeNode* root){
    if (root==NULL){
        return;
    }
    BinaryTreeNode *node = root;
    stack<BinaryTreeNode*>nodelist;
    while(!nodelist.empty()||node!=NULL){
        while(node!=NULL){
            nodelist.push(node);
            node = node->pLeft;
        }   
        node = nodelist.top();
        cout<<node->value;
        nodelist.pop();
        node = node->pRight;
    }
}

总结:
非递归式的前序和中序很相像,他们的区别在于修改了输出value的位置。原因在于前序是先输出根的值,再输出左节点的值;而中序是先输出左节点的值,再输出根的值。

非递归式后序遍历

void PostOrder1(BinaryTreeNode* root){
    if (root==NULL){
        return;
    }
    BinaryTreeNode *node = root;
    stack<BinaryTreeNode*>nodelist;
    BinaryTreeNode *pLastVisted = NULL;
    while(node!=NULL){
        nodelist.push(node);
        node = node->pLeft;
    }//先把所有的左节点放进去 
    while(!nodelist.empty()){
        node = nodelist.top();
        nodelist.pop();//取出栈顶节点 
        if(node->pRight==NULL || node->pRight==pLastVisted){//如果右子树为空或者右节点已经访问过了 
            cout<<node->value;
            pLastVisted=node; 
        }else{
            nodelist.push(node);//先将节点放回去 
            node = node->pRight;//取右节点 
            while(node){
                nodelist.push(node);
                node = node->pLeft;//放入左节点 
            }
        }
    }
}

总结:非递归式后序遍历用到了两个指针,其中一个要记录上一次遍历的那个节点。由于先输出左右节点的值,再输出根的值,因此在右节点还没有遍历的时候我们先将跟节点放回去,先遍历右子树,当右子树都遍历完了,再对根节点进行遍历。


最后附上我的main函数,一个简单建树的过程。

int main(){
    //initial
    BinaryTreeNode *node1 = new BinaryTreeNode();
    BinaryTreeNode *node2 = new BinaryTreeNode();
    BinaryTreeNode *node3 = new BinaryTreeNode();
    BinaryTreeNode *node4 = new BinaryTreeNode();
    BinaryTreeNode *node5 = new BinaryTreeNode();
    BinaryTreeNode *node6 = new BinaryTreeNode();
    node1->value = 1;
    node1->pLeft = node2;
    node1->pRight = node3;
    node2->value = 2;
    node2->pLeft = node4;
    node2->pRight = node5;
    node3->value = 3;
    node3->pLeft = node6;
    node3->pRight = NULL;
    node4->value = 4;
    node4->pLeft = NULL;
    node4->pRight = NULL;
    node5->value = 5;
    node5->pLeft = NULL;
    node5->pRight = NULL;
    node6->value = 6;
    node6->pLeft = NULL;
    node6->pRight = NULL;
    PreOrder1(node1);
    cout<<endl;
    InOrder1(node1);
    cout<<endl;
    PostOrder1(node1);
    cout<<endl;
    return 0;
} 

层次遍历

一般我们实现先序遍历、中序遍历和后序遍历都用的是stack这个数据结构,而在层次遍历中,我们用queue来实现。
···
vector< vector > levelOrder(TreeNode* root) {
vector< vector > result;
if(root==NULL)
return result;

    queue< TreeNode* > que;
    que.push(root);
    while(!que.empty()){
        vector<int> tmp;
        int size = que.size();
        for(int i=0;i< size;i++){
            TreeNode* node = que.front();
            que.pop();
            tmp.push_back(node->val);
            if(node->left){
                que.push(node->left);
            }
            if(node->right){
                que.push(node->right);
            }
        }
        result.push_back(tmp);
    }
    return result;
}

···

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值