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

来源:互联网 发布:Python程序sleep 编辑:程序博客网 时间:2024/06/05 06:35
#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<<")";        }    }}//递归遍历//PreOrdervoid BinaryTree::PreOrder(Node *subtree){    if(subtree!=NULL)    {        cout<<subtree->data<<" ";        PreOrder(subtree->lchild);        PreOrder(subtree->rchild);    }}//InOrdervoid BinaryTree::InOrder(Node *subtree){    if(subtree!=NULL)    {        InOrder(subtree->lchild);        cout<<subtree->data<<" ";        InOrder(subtree->rchild);    }}//PostOrdervoid 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());                                    //栈为空时退出循环}

 

0 0
原创粉丝点击