二叉树创建-- .cpp函数文件(无模板)

#include <iostream>
#include <stack>
#include <queue>
#include "binarytree.h"

istream& operator>>(istream &is,BinaryTree &BT)
{
    BT.CreateBT(is,BT);
    return is;
}
ostream& operator<<(ostream &os,BinaryTree &BT)
{
    os<<"按前序遍历的顺序输出二叉树:";
    BT.Traverse(os,BT.root);
    os<<endl;
    return os;
}

void BinaryTree::CreateBT(istream &is,BinaryTree &BT)
{
    cout<<"请以广义表的形式输入二叉树:"<<endl;
    cout<<"注意,左子女右子女有一个为空时,逗号不能省略,以#字符结束输入:"<<endl;
    stack<Node*> s;
    Node *p,*t;
    BT.root=NULL;
    char ch;
    int k=0;
    is>>ch;
    while(ch!=refvalue)
    {
        switch(ch)
        {
            case '(':s.push(p);k=1;break;                          //左括号,压入p即父母结点,同时k=1;
            case ')':s.pop();break;                                //右括号,退栈,即退出子树
            case ',':k=2;break;                                    //逗号,仅仅k=2,
            default:
                p=new Node(ch);                                    //新建结点p保存刚刚输入的数据
                if(BT.root==NULL) BT.root=p;                       //根结点赋值
                else if(k==1)                                      //链接左子树
                {
                    t=s.top();
                    t->lchild=p;
                }
                else if(k==2)                                      //链接右子树
                {
                    t=s.top();
                    t->rchild=p;
                }
        }
        is>>ch;
    }
}

void BinaryTree::Traverse(ostream &os,Node *subtree)
{

    if(subtree!=NULL)
    {
        os<<subtree->data<<" ";
        Traverse(os,subtree->lchild);
        Traverse(os,subtree->rchild);
    }
}


void PrintBT(Node *subtree)
{
    if(subtree!=NULL)
    {
        cout<<subtree->data<<" ";
        if(subtree->lchild!=NULL||subtree->rchild!=NULL)
        {
            cout<<"(";
            PrintBT(subtree->lchild);
            cout<<",";
            PrintBT(subtree->rchild);
            cout<<")";
        }
    }
}



//递归遍历
//PreOrder
void BinaryTree::PreOrder(Node *subtree)
{
    if(subtree!=NULL)
    {
        cout<<subtree->data<<" ";
        PreOrder(subtree->lchild);
        PreOrder(subtree->rchild);
    }
}
//InOrder
void BinaryTree::InOrder(Node *subtree)
{
    if(subtree!=NULL)
    {
        InOrder(subtree->lchild);
        cout<<subtree->data<<" ";
        InOrder(subtree->rchild);
    }
}
//PostOrder
void BinaryTree::PostOrder(Node *subtree)
{
    if(subtree!=NULL)
    {
        PostOrder(subtree->lchild);
        PostOrder(subtree->rchild);
        cout<<subtree->data<<" ";
    }
}

int BinaryTree::Size(Node *subtree)
{
    if(subtree==NULL) return 0;
    return 1+Size(subtree->lchild)+Size(subtree->rchild);
}

int BinaryTree::Height(Node *subtree)
{
    if(subtree==NULL) return 0;
    int i=Height(subtree->lchild);
    int j=Height(subtree->rchild);
    return (i>j)?i+1:j+1;
}

BinaryTree::BinaryTree(const BinaryTree &s)
{
    root=Copy(s.root);
}

Node* BinaryTree::Copy(Node *subtree)
{
    if(subtree==NULL) return NULL;

     Node *t=new Node;
     t->data=subtree->data;
     t->lchild=Copy(subtree->lchild);
     t->rchild=Copy(subtree->rchild);

    return t;
}
void BinaryTree::destroy(Node *subtree)
{
    if(subtree!=NULL)
    {
        destroy(subtree->lchild);
        destroy(subtree->rchild);
        delete subtree;
    }
}
//LevelOrder按层遍历
void BinaryTree::LevelOrder(Node *subtree)
{
    queue<Node *> q;
    q.push(subtree);
    Node *p;
    while(!q.empty())                            //循环直到队列空,跳出循环,每次循环压根结点的左右子女
    {
        p=q.front();                             //得到队首结点指针,
        cout<<p->data<<" ";                      //输出元素值
        q.pop();                                 //出队
        if(p->lchild!=NULL) q.push(p->lchild);   //左子女不为空,压左子女
        if(p->rchild!=NULL) q.push(p->rchild);   //右子女不为空,压右子女
    }

}
<pre name="code" class="cpp">//非递归遍历  栈的应用
//前序遍历 方法一 只压右子树

void BinaryTree::PreOrder(Node *subtree)
{
    stack<Node*> s;
    Node *p=subtree;
    s.push(NULL);
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        if(p->rchild!=NULL) {s.push(p->rchild);}                     //右子树不为空,压右子树
        if(p->lchild!=NULL) {p=p->lchild;}                           //左子树不为空,进入左子树,但不压栈
        else {p=s.top();s.pop();}                                    //左子树为空,退栈并得到栈顶元素
    }
}

//前序遍历  方法二 先压右子树,再压左子树
void BinaryTree::PreOrder(Node *subtree)
{
    stack<Node*> s;
    s.push(subtree);
    Node *p=subtree;
    while(!s.empty())
    {
        p=s.top();
        s.pop();
        cout<<p->data<<" ";
        if(p->rchild!=NULL) s.push(p->rchild);
        if(p->lchild!=NULL) s.push(p->lchild);

    }
}  

//前序遍历  方法三 压根结点
void BinaryTree::PreOrder(Node *subtree)
{
    stack <Node *> s;
    Node *p=subtree;
    while(p!=NULL||!s.empty())    //当且仅当栈空且p指向最右下方的空树跳出循环
    {
        if(p!=NULL)
        {
            cout<<p->data<<" ";   //输出根结点
            s.push(p);            //根结点入栈
            p=p->lchild;          //访问左子树
        }
        else
        {
            p=s.top();            //得到栈顶根节点指针
            s.pop();              //根节点出栈
            p=p->rchild;          //访问右子树
        }
    }
}

//中序遍历   方法一 压根结点
void BinaryTree::InOrder(Node *subtree)
{
    stack <Node *> s;
    Node *p=subtree;
    while(p!=NULL||!s.empty())
    {
        if(p!=NULL)
        {
           s.push(p);
           p=p->lchild;
        }
        else
        {
           p=s.top();
           s.pop();
           cout<<p->data<<" ";
           p=p->rchild;
        }
    }
}
//中序遍历

void BinaryTree::InOrder(Node *subtree)
{
    stack<Node*> s;
    Node *p=subtree;
    do{
        while(p!=NULL)
        {
            s.push(p);
            p=p->lchild;
        }

        if(!s.empty())
        {
            p=s.top();
            s.pop();
            cout<<p->data<<" ";
            p=p->rchild;
        }

    }while(!s.empty()||p!=NULL);
    cout<<endl;
}

//后序遍历,需要判断从左子树退回还是右子树退回,新建节点结构体,含标记值
struct stkNode                                            //遍历时所用栈结点类定义
{
    Node *ptr;                                         //指向树结点的指针
    int tag;                                       //该结点退栈的标记值,L代表从左子树退回,R代表从右子树退回
    stkNode(Node *N=NULL):ptr(N),tag(0){}              //构造函数,创建一个stkNode结点时,默认结点指针为NULL,标记值为L
};
void BinaryTree::PostOrder(Node *subtree)
{
    stack<stkNode> s;
    stkNode w;
    Node *p=subtree;                                   //p是遍历指针
    do
    {
        while(p!=NULL)                                    //向最左下方的结点循环下去,直到为空
        {
            w.ptr=p;                                      //左子树结点指针赋给w.ptr
            w.tag=0;                                      //w.tag赋为L标记
            s.push(w);                                    //压栈
            p=p->lchild;                                  //向左下方结点走下去
        }
        int continue1=1;                                  //循环的标记,用于当从右子树退回时,需要循环退栈两或多次
        while(continue1&&!s.empty())                      //栈不空则退栈
        {
            w=s.top();
            s.pop();
            p=w.ptr;
            switch(w.tag)                                 //判断栈顶结点指针的标记值
            {
            case 0:w.tag=1;                               //从左子树退回,则修改栈顶标记值后重新压栈
                   s.push(w);
                   continue1=0;                           //不是右子树退回,则不用再循环退栈,continue1赋为0
                   p=p->rchild;                           //访问右子树,跳到大循环do while中,将其左下方结点一直压栈……
                   break;
            case 1:cout<<w.ptr->data<<" ";                //从右子树退回,输出栈顶值,即根结点的值,继续循环退栈
                   break;
            }
        }
    }while(!s.empty());                                    //栈为空时退出循环
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值