二叉树遍历相关

红黑树也是二叉树,这里只是说明对树的遍历访问。插入、 查找、 删除 等操作参看红黑树那里

1、深度优先搜索:每种都有递归和迭代两种实现(迭代需要借助stack)

前序遍历:10,6,4,8,14,12,16

中序遍历:4,6,8,10,12,14,16(如果是二叉排序树就是输出排序结果了哈)

后序遍历:4,8,6,12,16,14,10

a.递归实现

递归实现相当简单:

void preOrder(BTree *tree)
{
    if(tree == NULL)
        return;
    //operator~~(前中后序不同就是此operator所在位置不同)
    if(tree->left)
        preOrder(tree->left);
    if(tree->right)
        preOrder(tree->right);
}

 

b.迭代实现

重点说下迭代实现:(有左子树就一直访问下去,直到没了再看右子树。感觉右子树都是挂在左子树上的啊。。。)

前序

void preOrder2(BTree *root)        //非递归前序遍历,按前序遍历走一遍就能理解他的思路了
{
    stack<BTree *> s;
    BTree *p=root;
    while(p!=NULL||!s.empty())        // 注意 p==NULL 时并不会退出while
    {
        while(p!=NULL)        //左子树非空时将一直遍历下去
        {
            cout<<p->data<<" ";
            s.push(p);
            p=p->lchild;
        }    //最后p肯定是一个叶子节点了(NULL)才退出while
        if(!s.empty())        //
        {
            p=s.top();
            s.pop();
            p=p->rchild;
        }
    }
}

中序

void inOrder2(BTree *root)        //非递归中序遍历
{
    stack<BTree*> s;
    BTree *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            cout<<p->data<<" ";
            s.pop();
            p=p->rchild;
        }
    }
}

后序

//非递归后序遍历相对复杂,可以沿承上面的做法,那就要在拿到s.top时候看是不是第一次处于top,如果是,那说明右子树还没有被访问呢,那就只是置flag,
//直接把右边孩子继续push。当第二次位于栈顶的时候就是该pop并访问此节点的时候。(这种做法需要在每个node里面加个flag)
void postOrder2(BTree *root)        //非递归后序遍历
{
    stack<BTNode*> s;
    BTree *p=root;
    BTNode *temp;        //这是新定义的node,多加了个flag
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)        //沿左子树一直往下搜索,直至出现没有左子树的结点
        {
            BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
            btn->btnode=p;
            btn->isFirst=true;
            s.push(btn);
            p=p->lchild;
        }
        if(!s.empty())
        {
            temp=s.top();
            s.pop();
            if(temp->isFirst==true)        //表示是第一次出现在栈顶
            {
                temp->isFirst=false;
                s.push(temp);
                p=temp->btnode->rchild;   
            }
            else        //第二次出现在栈顶
            {
                cout<<temp->btnode->data<<" ";
                p=NULL;
            }
        }
    }
}
//还有一种做法: http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html
void postOrder2(BinTree *root)        //非递归后序遍历
{
    stack<BinTree*> s;
    BinTree *cur;                                //当前结点
    BinTree *pre=NULL;                        //前一次访问的结点
    s.push(root);        //先把root入栈
    while(!s.empty())
    {
        cur=s.top();
        if( (cur->lchild==NULL && cur->rchild==NULL)||                  //当前节点为叶子节点
            (pre!=NULL && (pre==cur->lchild||pre==cur->rchild)))        //上一个访问的节点正是cur的右孩子,或者没有右孩子那就是是cur的左孩子。我感觉这里写的有问题
        {
            cout<<cur->data<<" ";  //如果当前结点没有孩子结点或者孩子节点都已被访问过
            s.pop();
            pre=cur;        //按照这个pop的顺序,pre 应该是 cur 的孩子
        }
        else
        {
            if(cur->rchild!=NULL)
                s.push(cur->rchild);   //注意这里先入栈的是cur的右孩子(保证pop的时候先出来的是left)
            if(cur->lchild!=NULL)
                s.push(cur->lchild);
        }
    }
}

2、宽度优先搜索

10,6,14,4,8,12,16。实现的话需要借助queue:

比如上面,A入队,queue<--A

A出队,并将A的所有child入队(BC入队),queue<--B<--C

B出队,并将B的所有child入队(DE入队),queue<--C<--D<--E

………………………

 

 

 

由二叉树的遍历引申出 求二叉树的深度

int GetTreeDeep(BinTree BT)  //类似后序遍历
{
    int deep=0;  //叶子节点深度为0
    if(BT)
    {         //左右子树的深度,二者较大者加1即是树的深度
        int lchilddeep = GetTreeDeep(BT->lchild);
        int rchilddeep = GetTreeDeep(BT->rchild);
        deep = (lchilddeep>=rchilddeep)? lchilddeep+1 : rchilddeep+1;
    }
    return deep;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值