链式二叉树的递归与遍历

来源:互联网 发布:淘宝无线端装修工具 编辑:程序博客网 时间:2024/04/29 21:39
//测试数据:EBH   GAC  F  D  #include<iostream>#include<cstdio>#include<stack>#include<queue>using namespace std;typedef char Elemtype;//定义这棵树的结点typedef struct node{    Elemtype data;    struct node *lchild;    struct node *rchild;}BitTree;//递归先序遍历void PreOrder(BitTree *bt){    if(bt!=NULL)    {        cout<<bt->data;        PreOrder(bt->lchild);        PreOrder(bt->rchild);    }}//非递归先序遍历void Preorder(BitTree *bt){    BitTree *p;    stack<BitTree *> s;    s.push(bt);    while(!s.empty())    {        p=s.top();        s.pop();        while(p)        {            cout<<p->data;            if(p->rchild) s.push(p->rchild);            p=p->lchild;        }    }}//递归中序遍历void InOrder(BitTree *bt){    if(bt!=NULL)    {        InOrder(bt->lchild);        cout<<bt->data;        InOrder(bt->rchild);    }}//非递归中序遍历void Inorder(BitTree *bt){    stack<BitTree *> s;    s.push(bt);    BitTree *p;    p=bt->lchild;    while(p||!s.empty())    {        while(p)        {            s.push(p);            p=p->lchild;        }        p=s.top();        s.pop();        cout<<p->data;        p=p->rchild;    }}//递归后序遍历void PostOrder(BitTree *bt){    if(bt!=NULL)    {        PostOrder(bt->lchild);        PostOrder(bt->rchild);        cout<<bt->data;    }}//非递归后序遍历void Postorder(BitTree *bt){    stack<BitTree *> s;    BitTree *p,*q;    p=bt;    q=NULL;    while(p||!s.empty())//使用p的原因是方便第一次进入,优化代码    {        if(p!=q)        {            while(p)            {                s.push(p);                if(p->lchild) p=p->lchild;                else p=p->rchild;            }        }        if(s.empty()) break;//写这句话的原因是访问根结点结束后,p为非空,所以还是能够进入循环,但堆栈已空,所以要用这句话推出        q=s.top();        if(q->rchild==p)        {            s.pop();            cout<<q->data;            p=q;        }        else p=q->rchild;    }}//二叉树的非递归层次遍历void levelBitTree(BitTree *bt){    queue<BitTree *> q;    BitTree *p;    p=NULL;    p=bt;    if(p) q.push(p);    while(!q.empty())    {        p=q.front();        q.pop();        cout<<p->data;        if(p->lchild) q.push(p->lchild);        if(p->rchild) q.push(p->rchild);    }}//建立二叉链表算法BitTree *creBitTree(){    BitTree *bt; Elemtype x;    scanf("%c",&x);    if(x==' ') bt=NULL;    else{        bt=(BitTree *)malloc(sizeof(BitTree));        bt->data=x;        bt->lchild=creBitTree();        bt->rchild=creBitTree();    }    return bt;}//统计二叉树中叶子节点的个数int cleaf=0;void countleaf(BitTree *bt){    if(bt!=NULL)    {        if(bt->lchild==NULL&&bt->rchild==NULL) cleaf++;        countleaf(bt->lchild);        countleaf(bt->rchild);    }}//交换二叉树中所有结点的左右子树void exchange(BitTree *bt){    BitTree *t;    if(bt!=NULL)    {        if(bt->lchild!=NULL||bt->rchild!=NULL)        {t=bt->lchild;bt->lchild=bt->rchild;bt->rchild=t;}        exchange(bt->lchild);        exchange(bt->rchild);    }}//求二叉树的高度int hightree(BitTree *bt){    int h,h1,h2;    if(bt==NULL) h=0;    else{        h1=hightree(bt->lchild);        h2=hightree(bt->rchild);        h=(h1>h2?h1:h2)+1;    }    return h;}//查找值为x的结点int ok=0;void searchtree(BitTree *bt,Elemtype x,BitTree **p1){    if(bt!=NULL&&!ok)    {        if(bt->data==x)        {ok=1;*p1=bt;}        else{            *p1=NULL;            searchtree(bt->lchild,x,p1);            searchtree(bt->rchild,x,p1);        }    }}//删除值为x的结点,使得其左右子树的安排仍然满足原来的中序遍历序列/*分析:为了保持中序遍历序列不变,对于找到的结点p可以分为4种情况考虑 (1)若结点p为叶子结点,则只需将该结点p的双亲结点f的左指针或右指针置为空即可 (2)若结点p的左子树为空,则只需将该结点p的双亲结点f的左指针或右指针指向该结点p的右孩子即可 (3)若结点p的左子树非空,则只需找到结点p的左子树中最右下的结点s(s的右指针必为空),将该结点s的左子树接到该结点s的双亲结点q上,再用该结点s中的数据替换p中的数据,最后删除该结点(s)即可 (4)若结点p为根结点bt且该结点左子树为空,则只需将根结点的指针bt移到结点p的右子树上即可 详细图解分析在 秦玉平 马靖善所编的数据结构(第三版) p129-129的例5.14*///为了此功能专门设计的查找函数,f记录双亲结点,p记录查找到的结点int Find=0;void search(BitTree *bt,Elemtype x,BitTree **p,BitTree **f){    if(bt!=NULL&&!Find)    {        if(bt->data==x)        {Find=1;*p=bt;}        else{            if(!Find){                *f=bt;                search(bt->lchild,x,p,f);            }            if(!Find){                *f=bt;                search(bt->rchild,x,p,f);            }        }    }}//删除x的函数void deltree(BitTree **bt,Elemtype x){    BitTree *p,*f;    BitTree *q,*s;    p=f=NULL;    search(*bt,x,&p,&f);    if(p!=NULL)    {        if(p->lchild!=NULL)        {            q=p->lchild;            s=q;            while(s->rchild!=NULL){q=s;s=s->rchild;}            if(q!=s) q->rchild=s->lchild;            else p->lchild=q->lchild;            p->data=s->data;            free(s);        }        else{             if(f!=NULL){                if(p==f->lchild) f->lchild=p->rchild;                else f->rchild=p->rchild;             }            else                *bt=(*bt)->rchild;            free(p);        }    }    else        cout<<"Not find this node"<<endl;}int main(){    BitTree *bt;//    BitTree **p1;//    Elemtype x;//    Elemtype y;//    int h;    bt=creBitTree();//建树//    PreOrder(bt);//递归先序//    cout<<endl;//    InOrder(bt);//递归中序//    cout<<endl;//    PostOrder(bt);//递归后序//    cout<<endl;//    countleaf(bt);//统计叶子结点个数//    cout<<cleaf<<endl;//    exchange(bt);//    PreOrder(bt);//递归先序//    cout<<endl;//    InOrder(bt);//递归中序//    cout<<endl;//    PostOrder(bt);//递归后序//    cout<<endl;//    h=hightree(bt);//求树的高度//    cout<<h<<endl;//    cin>>x;//    p1=(BitTree **)malloc(sizeof(BitTree));//给**p开辟空间//    searchtree(bt,x,p1);//找到x,并把x的地址存放在p里面,注意,p放的是x的地址,而不是这个地址里的内容//    cout<<(*p1)->data<<endl;//输出p指的内容,也就是找到的x//    cin>>y;//    deltree(&bt,y);//    InOrder(bt);//递归中序//    cout<<endl;//    Preorder(bt);//非递归先序遍历//    cout<<endl;//    Inorder(bt);//非递归中序遍历//    cout<<endl;//    Postorder(bt);//非递归后序遍历//    cout<<endl;    levelBitTree(bt);    cout<<endl;    return 0;}

0 0
原创粉丝点击