数据结构——二叉树

存放的是二叉树的建立,遍历等一些算法操作,没有在主函数中调BUG,以后有时间会回来仔细推敲!!!

注意二叉树的递归建立操作,最后一定要有TreeNode*root=create(root)这一步,否则原来指针变量的值没有被改变,那么在后续操作中可能会有麻烦,这和函数的拷贝传参有关,递归调用时,修改的只是备份的指针变量,而非原本的指针变量!!!! 

//二叉树
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
//二叉树节点(储存自然数整形数据)
//三叉链节点
typedef struct TreeNode_th
{
    int data;//数据域
    TreeNode_th*leftchild;//左孩子
    TreeNode_th*rightchild;//右孩子
    TreeNode_th*parents;//父母节点
    TreeNode_th(int x):data(x){};//数据域赋值
}TreeNode_th;
//二叉链节点
typedef struct TreeNode
{
    int data;//数据域
    TreeNode*leftchild;//左孩子
    TreeNode*rightchild;//右孩子
    TreeNode(int x):data(x){};//数据域赋值
}TreeNode;
class Tree
{
public:
    //树的递归操作
    TreeNode*RQA_CreateTree_Two(TreeNode*op);//递归创建二叉树——二叉链表
    void RQA_PreOrder(TreeNode*op);//递归前序遍历输出二叉树
    void RQA_InOrder(TreeNode*op);//递归中序遍历输出二叉树
    void RQA_PostOrder(TreeNode*op);//递归后续遍历输出二叉树
    int LeavesNums(TreeNode*op);//递归计算树的所有叶子节点
    int AllNums(TreeNode*op);//递归计算树的所有节点
    int TreeDepth(TreeNode*op);//递归计算树的深度
    void CopyTree(TreeNode*op1,TreeNode*op2);//递归复制一棵二叉树
    TreeNode*SwapLRTree(TreeNode*op1,TreeNode*op2);//递归镜像二叉树——返回交换二叉树的左子树和右子树后的二叉树,原树结构不变
    int CountK(TreeNode*op,int k);//递归计算二叉树中值是k的节点的个数
    void ReleaseTree(TreeNode*op);//递归删除二叉树
    TreeNode* ParentNode(TreeNode*op,int k);//递归寻找二叉树的任意一个节点的父节点
    TreeNode*InExchangeTree(TreeNode*op);//递归镜像二叉树——返回交换二叉树的左子树和右子树后的二叉树,原树结构改变
    void DeletexTree(TreeNode*op,int x);//递归删除以数据x为根节点的树
    int*TranstoArray(TreeNode*op,int*res,int index);//递归把二叉树转为静态数组顺序储存
    //树的非递归操作
    void PreOrder(TreeNode*op);//非递归前序遍历输出二叉树
    void InOrder(TreeNode*op);//非递归中序遍历输出二叉树
    void PostOrder(TreeNode*op);//非递归后续遍历输出二叉树
    void Queue_LeverOrder(TreeNode*op);//队列层序遍历输出二叉树
    void SwapTree(TreeNode*op1,TreeNode*op2);//非递归的交换两棵二叉树中的内容
};
//递归——创建二叉树——二叉链表
TreeNode*Tree::RQA_CreateTree_Two(TreeNode*op)
{
    int Ai;
    cin>>Ai;
    if(Ai<0)
        op=nullptr;
    op=new TreeNode(Ai);
    op->leftchild=RQA_CreateTree_Two(op->leftchild);
    op->rightchild=RQA_CreateTree_Two(op->rightchild);
    return op;
}
//递归——前序
void Tree::RQA_PreOrder(TreeNode*op)
{
    if(op==nullptr)
        return;
    cout<<op->data;
    RQA_PreOrder(op->leftchild);
    RQA_PreOrder(op->rightchild);
}
//递归——中序
void Tree::RQA_InOrder(TreeNode*op)
{
    if(op==nullptr)
        return;
    RQA_InOrder(op->leftchild);
    cout<<op->data;
    RQA_InOrder(op->rightchild);
}
//递归——后序
void Tree::RQA_PostOrder(TreeNode*op)
{
    if(op==nullptr)
        return ;
    RQA_PostOrder(op->leftchild);
    RQA_PostOrder(op->rightchild);
    cout<<op->data;
}
//队列——层序
void Tree::Queue_LeverOrder(TreeNode*op)
{
    queue<TreeNode*>oop;
    TreeNode*front_q;
    oop.push(op);
    while(!oop.empty())
    {
        front_q=oop.front();
        oop.pop();
        if(front_q->leftchild!=nullptr)
            oop.push(front_q->leftchild);
        if(front_q->rightchild!=nullptr)
            oop.push(front_q->rightchild);
        cout<<front_q->data;
    }
}
//非递归——前序——栈
void Tree::PreOrder(TreeNode*op)
{
     stack<TreeNode*> s;
     TreeNode*cur,*top;
     cur=op;
     while(cur!=nullptr||!s.empty())
     {
         while(cur!=nullptr)
         {
             cout<<cur->data;
             s.push(cur);
             cur=cur->leftchild;
         }
         top=s.top();
         s.pop();
         cur=top->rightchild;
     }
}
//非递归——中序——栈
void Tree::InOrder(TreeNode*op)
{
    stack<TreeNode*>s;
    TreeNode*cur,*top;
    cur=op;
    while(cur!=nullptr||!s.empty())
    {
        while(cur!=nullptr)
        {
            s.push(cur);
            cur=cur->leftchild;
        }
        top=s.top();
        s.pop();
        cout<<top->data;
        cur=top->rightchild;
    }
}
//非递归——后序——栈
void Tree::PostOrder(TreeNode*op)
{
    stack<TreeNode*>s;
    TreeNode*cur,*top;
    TreeNode*last=nullptr;
    cur=op;
    while(cur!=nullptr||s.empty())
    {
        while(cur!=nullptr)
        {
            s.push(cur);
            cur=cur->leftchild;
        }
        top=s.top();
        if(top->rightchild==nullptr||top->rightchild==last)//如果该节点的右子树不存在,或者该节点右子树已经被遍历过了
        {
            s.pop();//弹出该节点
            cout<<top->data;//输出节点
            last=top;//记录这个节点已经被遍历过了
        }
        else
        {
            cur=top->rightchild;
        }
    }
}
//树的叶子节点的个数——递归
int Tree::LeavesNums(TreeNode*op)
{
    if(op==nullptr)
        return 0;
    if(op->leftchild==nullptr&&op->rightchild==nullptr)
        return 1;
    int num_left=0,num_right=0;
    num_left=LeavesNums(op->leftchild);
    num_right=LeavesNums(op->rightchild);
    return (num_left+num_right);
}
//树的节点的总数——递归
int Tree::AllNums(TreeNode*op)
{
    if(op==nullptr)
        return 0;
    return AllNums(op->leftchild)+AllNums(op->rightchild)+1;
}
//树的深度——递归
int Tree::TreeDepth(TreeNode*op)
{
    if(op==nullptr)
        return 0;
    int left_depth=TreeDepth(op->leftchild);//求左子树的深度
    int right_depth=TreeDepth(op->rightchild);//求右子树的深度
    //取两棵子树中深度较大的那一棵子树
    if(left_depth>right_depth)
        return left_depth+1;//加上根节点的深度
    else
        return right_depth+1;
}
//k的节点的个数——递归
int Tree::CountK(TreeNode*op,int k)
{
    if(op==nullptr)
        return 0;
    if(op->data==k)
        return(CountK(op->leftchild,k)+CountK(op->rightchild,k)+1);
    return(CountK(op->leftchild,k)+CountK(op->rightchild,k));
}
//复制一棵二叉树——递归——把op1复制到op2中
void Tree::CopyTree(TreeNode*op1,TreeNode*op2)
{
    if(op1==nullptr)
        op2=nullptr;
    //op2->data=op1->data;//注意在这里不给op2申请节点空间是不行的,不申请的话就会无法使用data,leftchild,rightchild等节点元素
    op2=new TreeNode(op1->data);
    CopyTree(op1->leftchild,op2->leftchild);
    CopyTree(op1->rightchild,op2->rightchild);
}
//镜像二叉树——递归——op2是op1镜像之后的树
TreeNode* Tree::SwapLRTree(TreeNode*op1,TreeNode*op2)
{
    if(op1==nullptr)
        return nullptr;
    op2=new TreeNode(op1->data);
    SwapLRTree(op1->leftchild,op2->rightchild);//op1的左子树是op2的右子树
    SwapLRTree(op1->rightchild,op2->leftchild);//op1的右子树是op2的左子树
}
//删除二叉树——递归
void Tree::ReleaseTree(TreeNode*op)
{
    if(op==nullptr)
        return;//递归终止条件
    ReleaseTree(op->leftchild);
    ReleaseTree(op->rightchild);
    delete op;
}
//寻找任意一个节点的父节点,寻找值为k的节点的父节点
TreeNode* Tree::ParentNode(TreeNode*op,int k)
{
    if(op==nullptr)
        return nullptr;
    if(op->data==k)//如果根节点的值是k
        return nullptr;
    if((op->leftchild!=nullptr&&op->leftchild->data==k)||(op->rightchild!=nullptr&&op->rightchild->data))//如果找到了一个左右孩子中有k值的,返回当前节点
        return op;
    TreeNode*res=nullptr;
    res=ParentNode(op->leftchild,k);
    res=ParentNode(op->rightchild,k);
    return res;//这样的顺序会以右子树的k父母节点为优先返回,如果遍历树玩了都没有找到就直接返回一个空指针
}
//自身镜像二叉树——递归
TreeNode* Tree::InExchangeTree(TreeNode*op)
{
    if(op==nullptr)
        return nullptr;
    TreeNode*temp;
    temp=op->leftchild;
    op->leftchild=op->rightchild;
    op->rightchild=temp;
    if(op->leftchild!=nullptr)
        InExchangeTree(op->leftchild);
    if(op->rightchild)
        InExchangeTree(op->rightchild);
    return op;
}
//删除以x为根节点的树——递归
void Tree::DeletexTree(TreeNode*op,int x)
{
    if(op==nullptr)
        return ;
    if(op->data==x)
    {
        ReleaseTree(op);
        op=nullptr;
    }
    //根据算法顺序可知,这样会把左右子树所有以x为根节点的树删除
    DeletexTree(op->leftchild,x);
    DeletexTree(op->rightchild,x);
}
//把二叉树转为静态数组顺序储存——递归——显然这里使用vector更好
int* Tree::TranstoArray(TreeNode*op,int*res,int index)
{
    if(op==nullptr)
        return nullptr;
    res[index]=op->data;
    index++;
    TranstoArray(op->leftchild,res,index);
    TranstoArray(op->rightchild,res,index);
    return res;
    //心存疑惑
    /*if(op!=nullptr)
    {
        res[index]=op->data;
        TranstoArray(op->leftchild,res,2*index);
        TranstoArray(op->rightchild,res,2*index+1);
    }
    else
    {
        A[index]=-1;//标记为空节点!
    }
    return res;*/
}
//交换两棵二叉树中的内容——调用已定义的函数——非递归(注意一下啊!!以后有时间要修改啊!!!!!)
void Tree::SwapTree(TreeNode*op1,TreeNode*op2)
{
    TreeNode*temp;

    CopyTree(op1,temp);
    ReleaseTree(op1);

    CopyTree(op2,op1);
    ReleaseTree(op2);

    CopyTree(temp,op2);
    ReleaseTree(temp);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值