2020-9-27 严蔚敏《数据结构》 二叉链表: 递归、非递归(非递归用栈)先序、中序、后序遍历(非递归后序遍历麻烦点,需要用到flag标志)以及层序遍历(层序用队列),以及建立在遍历上的一些操作

//严蔚敏《数据结构》
//二叉链表: 递归、非递归(非递归用栈)先序、中序、后序遍历(非递归后序遍历麻烦点,需要用到flag标志)
//以及层序遍历(层序用队列),以及建立在遍历上的一些操作

//思考:对二叉链表的操作几乎都是建立在遍历的基础上(所以说遍历很重要!!)
//若为简单的输出遍历,递归容易实现,但效率较低;
//若不是简单的输出,是建立在遍历基础上的一些操作,比如 寻找双亲,非递归容易实现
//5-7行是基于现在水平的我的理解,可能不太对,我会回来的

//自学中,加油!!!
#include<iostream>
using namespace std;
#define TElemType double

typedef struct BiTNode
{
    TElemType data;
    struct BiTNode* lchild,* rchild;
    int flag;//标志变量 标志非递归的后序遍历
}BiTNode,* BiTree;

bool Creat_BiTree(BiTree& T)//递归先序创建并输入
{
    TElemType num;
    if(cin>>num){//此处应用if而不是while循环  这是在用递归,就不用while循环了
        T=new BiTNode;
        if(!T)
            return false;
        T->data=num;
        Creat_BiTree(T->lchild);
        Creat_BiTree(T->rchild);
    }
    if(!cin)
        T=nullptr;
    if(!cin){
        cin.clear();
        while(cin.get()!='\n')
            continue;
    }
    return true;
}

void PreOrder_Bitree(BiTree T)//递归先序遍历
{
    if(T){
        cout<<T->data<<endl;
        PreOrder_Bitree(T->lchild);
        PreOrder_Bitree(T->rchild);
    }
}

void InOrder_bitree(BiTree T)//递归中序遍历
{
    if(T){
        InOrder_bitree(T->lchild);
        cout<<T->data<<endl;
        InOrder_bitree(T->rchild);
    }
}

void PostOrder_BiTree(BiTree T)//递归后序遍历
{
    if(T){
        PostOrder_BiTree(T->lchild);
        PostOrder_BiTree(T->rchild);
        cout<<T->data<<endl;
    }
}
//构造的队列为层序遍历服务
#define QElemType BiTree
typedef struct QNode
{
    QElemType data;
    struct QNode* next;
}QNode,* QPtr;

typedef struct
{
    QPtr head,tail;
    int length;
}QueueList;

bool Init_Queue(QueueList& Q)
{
    Q.head=new QNode;
    if(!Q.head)
        return false;
    Q.head->next=nullptr;
    Q.tail=Q.head;
    Q.length=0;
    return true;
}

bool IsEmpty_Queue(QueueList Q)
{
    if(Q.length)
        return false;
    return true;
}

bool Push_Queue(QueueList& Q,QElemType e)
{
    QPtr p=new QNode;
    if(!p)
        return false;
    p->data=e;
    p->next=Q.tail->next;
    Q.tail->next=p;
    Q.tail=p;
    Q.length++;
    return true;
}

bool Pop_Queue(QueueList& Q,QElemType& e)
{
    if(IsEmpty_Queue(Q))
        return false;
    QPtr p=Q.head->next;
    e=p->data;
    Q.head->next=p->next;
    if(p==Q.tail)//若头指针后面就是尾指针,需改动Q.tail的值
        Q.tail=Q.head;
    delete p;
    Q.length--;//bug2:忘记该行代码
    return true;
}

void LevelOrder_BiTree(BiTree T)//利用队列层序遍历
{
    QueueList Q;
    Init_Queue(Q);
    Push_Queue(Q,T);
    while(!IsEmpty_Queue(Q)){
        BiTree bt;
        Pop_Queue(Q,bt);
        cout<<bt->data<<endl;
        if(bt->lchild)
            Push_Queue(Q,bt->lchild);
        if(bt->rchild)
            Push_Queue(Q,bt->rchild);
    }
}
//构造的栈为非递归 先序、中序、后序遍历服务
#define SElemType BiTree
typedef struct SNode
{
    SElemType data;
    struct SNode* next,* prior;
}SNode,* SLink;

typedef struct
{
    SLink head,tail;
    int length;
}LinkStack;

bool Init_Stack(LinkStack& S)
{
    S.head=new SNode;
    if(!S.head)
        return false;
    S.head->next=S.head->prior=nullptr;
    S.tail=S.head;
    S.length=0;
    return true;
}

bool IsEmpty_Stack(LinkStack S)
{
    if(!S.length)
        return true;
    return false;
}
SElemType GetTop_Stack(LinkStack S)
{
    return S.tail->data;
}

bool Push_Stack(LinkStack& S,SElemType e)
{
    SLink p=new SNode;
    if(!p)
        return false;
    p->data=e;
    p->next=S.tail->next;
    S.tail->next=p;
    p->prior=S.tail;
    S.tail=p;
    S.length++;
    return true;
}

bool Pop_Stack(LinkStack& S,SElemType& e)
{
    SLink p=S.tail;
    e=S.tail->data;
    S.tail=S.tail->prior;
    S.tail->next=p->next;
    delete p;
    S.length--;
    return true;
}

void PreOrder_Bitree1(BiTree bt)//非递归先序遍历 使用栈
{
    BiTree T=bt;
    LinkStack S;
    Init_Stack(S);
    while(T||!IsEmpty_Stack(S)){
        while(T){
            cout<<T->data<<endl;
            Push_Stack(S,T);
            T=T->lchild;
        }
        if(!IsEmpty_Stack(S)){
            Pop_Stack(S,T);
            T=T->rchild;
        }
    }
}

void InOrder_bitree1(BiTree bt)//非递归中序遍历 使用栈
{
    BiTree T=bt;
    LinkStack S;
    Init_Stack(S);
    while(T||!IsEmpty_Stack(S)){
        while(T){//T一直向左遍历,并将沿途结点压入栈
            Push_Stack(S,T);
            T=T->lchild;
        }
        if(!IsEmpty_Stack(S)){//从栈中得到双亲
            Pop_Stack(S,T);
            cout<<T->data<<endl;//打印结点数据
            T=T->rchild;
        }
    }
}

void PostOrder_BiTree1(BiTree bt)//非递归后序遍历 使用栈
{
    BiTree T=bt;
    LinkStack S;
    Init_Stack(S);
    while(T||!IsEmpty_Stack(S)){
        while(T){//T一直向左遍历,并将沿途结点压入栈
            T->flag=0;//在入栈之前将T->flag置为0,不然在main调用两次PostOrder_BiTree1,第二个会发生错误
            Push_Stack(S,T);
            T=T->lchild;
        }
        while(!IsEmpty_Stack(S)&&GetTop_Stack(S)->flag==1){
            Pop_Stack(S,T);
            cout<<T->data<<endl;//打印结点数据
        }
        if(!IsEmpty_Stack(S)){//若flag不为1,则不输出,然后继续向右子树遍历
            T=GetTop_Stack(S);
            T->flag=1;
            T=T->rchild;
        }
        else//左->右->根  当栈空时,遍历已经全部完成
            break;
    }
}
//以下的操作大多建立在遍历的基础之上 根据不同的要求进行不同的遍历
BiTree Clear_BiTree(BiTree& T)//清空二叉链表(选择递归后序遍历,好处:左右子树操作完后,才进行根的删除)
{
    BiTree bt=T;
    if(bt){
        bt->lchild=Clear_BiTree(bt->lchild);
        bt->rchild=Clear_BiTree(bt->rchild);
        delete bt;
        return nullptr;
    }
}

bool IsEmpty_BiTree(BiTree T)//二叉链表为空,返回true;否则返回false
{
    if(!T)
        return true;
    return false;
}

int Depth_BiTree(BiTree T)//返回二叉树的深度(采用递归后序遍历,先找Max(H左,H右),然后将其+1
{
    if(T){
        int Depth1=Depth_BiTree(T->lchild);
        int Depth2=Depth_BiTree(T->rchild);
        return (Depth1>Depth2?Depth1:Depth2)+1;
    }
    return 0;
}

BiTree Root(BiTree T)//返回指向根的指针
{
    return T;
}
/*
bool Value_BiTree(BiTree T,BiTree p)//输出p指向树结点的数据(这个三个次序都可以,在此我选择先序了)
{
    BiTree bt=T;
    if(bt){
        if(p==bt){
            cout<<bt->data;
        }
        Value_BiTree(bt->lchild,p);
        Value_BiTree(bt->rchild,p);
    }
    return true;
}
*/
//291-304行代码  输出选择递归,若函数类型为返回,递归不太好完成,在此选择非递归先序
TElemType Value_BiTree(BiTree T,BiTree p)
{
    BiTree bt=T;
    LinkStack S;
    Init_Stack(S);
    while(bt||!IsEmpty_Stack(S)){//bug1: 将||写为&&
        while(bt){
            if(bt==p)
               return bt->data;
            Push_Stack(S,bt);
            bt=bt->lchild;
        }
        if(!IsEmpty_Stack(S)){
            Pop_Stack(S,bt);//此处应为Pop_Stack(S,bt) 而不是Pop_Stack(S,e)
            bt=bt->rchild;
        }
    }
}

bool Assign_BiTree(BiTree& T,BiTree p,TElemType e)//将数据e赋给p指向树节点的数据域(递归先序遍历)
{
    //BiTree bt=T;//递归不要这一行,非递归需要
    if(T){
        if(T==p){
            T->data=e;
        }
        Assign_BiTree(T->lchild,p,e);
        Assign_BiTree(T->rchild,p,e);
    }
    return true;
}

bool Assign_BiTree1(BiTree& T,BiTree p,TElemType e)//非递归先序遍历
{
    BiTree bt=T;
    LinkStack S;
    Init_Stack(S);
    while(bt||!IsEmpty_Stack(S)){
        while(bt){
            if(p==bt){
                bt->data=e;
            }
            Push_Stack(S,bt);
            bt=bt->lchild;
        }
        if(!IsEmpty_Stack(S)){
            Pop_Stack(S,bt);
            bt=bt->rchild;
        }
    }
    return true;
}

//输出 选择递归较容易,非输出 递归、非递归均可,看情况使用。若函数类型为返回,递归不太好完成,在此选择非递归先序
void Parent_BiTree(BiTree T,BiTree p)//输出树指针p的双亲(选择递归先序遍历)   递归输出
{
    if(T){
        if(T->lchild==p||T->rchild==p)
            cout<<T->data<<endl;
        Parent_BiTree(T->lchild,p);
        Parent_BiTree(T->rchild,p);
    }
}

BiTree Parent_BiTree1(BiTree T,BiTree p)//非递归返回  先序遍历
{
    BiTree bt=T;
    LinkStack S;
    Init_Stack(S);
    if(T==p)//p为总根,无双亲
        return nullptr;
    while(bt||!IsEmpty_Stack(S)){
        while(bt){
            if(bt->lchild==p||bt->rchild==p)
               return bt;
            Push_Stack(S,bt);
            bt=bt->lchild;
        }
        if(!IsEmpty_Stack(S)){
            Pop_Stack(S,bt);
            bt=bt->rchild;
        }
    }
    return nullptr;
}
//二叉链表找双亲、兄弟需要从头开始遍历 找孩子不需要遍历
BiTree LeftChild_BiTree(BiTree T,BiTree p)//返回树指针p的左孩子,若无,返回nullptr
{
    return p->lchild;
}

BiTree RightChild_BiTree(BiTree T,BiTree p)//返回树指针p的右孩子,若无,返回nullptr
{
    return p->rchild;
}

BiTree LeftSibling(BiTree T,BiTree p)//返回树指针p的左兄弟指针,若无,返回nullptr
{
    return Parent_BiTree1(T,p)->lchild;
}

BiTree RightSibling(BiTree T,BiTree p)//返回树指针p的右兄弟指针,若无,返回nullptr
{
    return Parent_BiTree1(T,p)->rchild;
}

bool InsertChild_BiTree(BiTree& T,BiTree p,int LR,BiTree e)//LR=0:插入数据e到p指针的左孩子结点
                                                           //LR=1:插入数据e到p指针的右孩子结点
{
    if(LR==0){
        if(!p->lchild){
            p->lchild=e;
            return true;
        }
        return false;
    }
    else{
        if(!p->rchild){
            p->rchild=e;
            return true;
        }
        return false;
    }
}

bool DeleteChild_BiTree(BiTree& T,BiTree p,int LR,BiTree e)//LR=0:删除p指针的子树(采用非递归后序遍历 ,最后删除根)
                                                           //LR=1:删除p指针的子树
{
    BiTree bp=p;
    if(LR==0){
        bp=p->lchild;
        p->lchild=nullptr;
    }
    else{
        bp=p->rchild;
        p->rchild=nullptr;
    }
    LinkStack S;
    Init_Stack(S);
    while(bp&&!IsEmpty_Stack(S)){
        while(bp){
            bp->flag=0;//入栈前设置bp->flag=0
            Push_Stack(S,bp);
            bp=bp->lchild;
        }
        while(!IsEmpty_Stack(S)&&GetTop_Stack(S)->flag==1){
            Pop_Stack(S,bp);
            delete bp;
        }
        if(!IsEmpty_Stack(S)){
            bp=GetTop_Stack(S);
            bp->flag=1;
            bp=bp->rchild;
        }
        else
            break;
    }
    return true;
}
//while循环可以替代递归

int main()
{
    BiTree T;
    Creat_BiTree(T);
    cout<<"非递归后序遍历\n";
    PostOrder_BiTree1(T);//非递归 记得将flag 重置为0

    /*T=Clear_BiTree(T);
    cout<<"非递归后序遍历\n";//Clear_BiTree的测试代码
    PostOrder_BiTree1(T);*/

    /*cout<<"深度:"<<Depth_BiTree(T)<<endl;
    cout<<"非递归后序遍历\n";
    PostOrder_BiTree1(T);
    cout<<"值:"<<Value_BiTree(T,T->lchild->rchild->lchild)<<endl;
    Assign_BiTree1(T,T->lchild->rchild,9.9);
    cout<<"非递归后序遍历\n";
    PostOrder_BiTree1(T);
    Assign_BiTree(T,T->lchild->rchild,11.1);
    cout<<"非递归后序遍历\n";
    PostOrder_BiTree1(T);*///Clear_BiTree Depth_BiTree  Assign_BiTree操作的测试代码

    /*cout<<"====="<<endl;
    Parent_BiTree(T,T->lchild->rchild);
    cout<<"====="<<endl;
    cout<<Parent_BiTree1(T,T->lchild->rchild->lchild)->data<<endl;
    cout<<"====="<<endl;
    cout<<LeftChild_BiTree(T,T->lchild->rchild)->data<<endl;
    cout<<"====="<<endl;
    cout<<RightChild_BiTree(T,T->lchild->rchild)<<endl;
    cout<<"===="<<endl;
    cout<<LeftSibling(T,T->lchild->rchild)->data<<endl;
    cout<<"===="<<endl;
    cout<<RightSibling(T,T->lchild)->data;*///Parent、LeftChild、RightChild、LeftSibling、RightSibling
                                            //操作的测试代码
    //下面为测试 InsertChild、deleteChild操作的代码
    BiTree T2;
    Creat_BiTree(T2);
    cout<<"非递归后序遍历\n";
    PostOrder_BiTree1(T2);
    InsertChild_BiTree(T,T->lchild->lchild,0,T2);
    cout<<"非递归后序遍历\n";
    PostOrder_BiTree1(T);
    DeleteChild_BiTree(T,T->lchild->lchild,0,T2);
    cout<<"非递归后序遍历\n";
    PostOrder_BiTree1(T);
    return 0;
}

main函数的测试图如下所示
在这里插入图片描述

1.1
2.2
4.4
@
6.6
@
@
5.5
7.7
@
@
@
3.3
@
@
非递归后序遍历
6.6
4.4
7.7
5.5
2.2
3.3
1.1
8.8
9.9
@
11.1
@
@
12.2
@
13.3
@
@
非递归后序遍历
11.1
9.9
13.3
12.2
8.8
非递归后序遍历
11.1
9.9
13.3
12.2
8.8
6.6
4.4
7.7
5.5
2.2
3.3
1.1
非递归后序遍历
6.6
4.4
7.7
5.5
2.2
3.3
1.1

Process returned 0 (0x0)   execution time : 16.433 s
Press any key to continue.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值