森林与二叉树(命令行可视化版本)

如何使用命令行进行虚假的可视化

题目见我的另一篇博客:传送门
本文是这篇博客的可视化版本,使用命令行可视化,能够实现森林中各个树的孩子兄弟表示法可视化以及二叉树可视化,截图如下:
在这里插入图片描述
可视化操作涉及到的函数主要是:

void linkedBinaryTree::inorder(binaryTreeNode *t);//用于确定横纵坐标
void linkedBinaryTree::visualTree();//可视化
void linkedBinaryTree::visual_binaryTree();//可视化二叉树
void Forest::visual_forest(int m);//可视化森林

第一个函数是中序遍历函数,中序遍历后的结果就是各个结点相对的横坐标位置(最后还要调整),在中序遍历的过程中,还记录了各点的纵坐标。所以这就解释了森林我为什么要用二叉树的形式进行可视化,毕竟森林无法中序遍历。

第二个函数是可视化函数,使用层次遍历的方式进行可视化,从横向来看,控制方法是计算当前结点的横坐标,在代码中涉及到一个计算公式:数字长度=(int)log10(数字)+1。然后我们可以对其除2上取整来计算当前数字的相对中心,然后判断当前行前面输出了多少个字符来确定输出空格的数量,判断左右孩子结点情况输出对应位置的’_’。

第三个函数是可视化二叉树,功能是将根结点加入层次遍历的队列,便于进行可视化操作。

第四个函数是可视化森林函数。此函数将所有树的跟结点加入队列,便于可视化。需要注意的是,由于我们森林的存储方式是一整棵二叉树,所以函数中需要对所有要加入的结点进行处理,将其右兄弟的结点临时保存在temprightChild数组中,并且将其右兄弟指针指向空。在可视化结束后,重新通过该数组进行赋值。

完整代码如下:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

const int maxn=5110;
struct binaryTreeNode//二叉树结点
{
    int element;
    int x,y;//当前结点的横纵坐标
    binaryTreeNode *leftChild,*rightChild;
    binaryTreeNode() {leftChild=rightChild=nullptr; element=0;x=y=0;}
    binaryTreeNode(const int& theElement){
        element=theElement;
        leftChild=rightChild=nullptr;
        x=y=0;
    }
    binaryTreeNode(const int& theElement,binaryTreeNode *theLeftChild,binaryTreeNode *theRightChild,int _x,int _y){
        element=theElement;
        leftChild=theLeftChild;
        rightChild=theRightChild;
        x=_x; y=_y;
    }
};
class linkedBinaryTree//二叉树类
{
public:
    linkedBinaryTree(int _root=0){
        leaf=new binaryTreeNode*[maxn];
        for (int i=0; i<maxn; i++) leaf[i]=nullptr;
    }
    void init(int _root){
        leaf[_root]=new binaryTreeNode(_root);
        root=leaf[_root];
    }
    bool insert(int father,int node,int lr);
    void insert_l_r(int father,int left,int right);
    int showTheBinaryTree(binaryTreeNode *t);
    void preorder(binaryTreeNode *t,int &ans);
    void inorder(binaryTreeNode *t);
    void visualTree();
    void visual_binaryTree();
    binaryTreeNode* getTheRoot(){return root;}
    void output(binaryTreeNode* t);
    binaryTreeNode* binaryTree_to_forest();
    void copy1(binaryTreeNode *node);
    void from_forest(binaryTreeNode *t);

protected:
    binaryTreeNode* root;
    binaryTreeNode** leaf;
    queue<binaryTreeNode* > q;
    vector<int> v;//存储中序遍历的结果,以便于计算横坐标

};
void linkedBinaryTree::inorder(binaryTreeNode *t)//用于确定横纵坐标
{
    if(t!=nullptr){
        if(t->leftChild!=nullptr) t->leftChild->y=t->y+1;
        inorder(t->leftChild);
        v.push_back(t->element);
        if(t->rightChild!=nullptr) t->rightChild->y=t->y+1;
        inorder(t->rightChild);
    }
}
void linkedBinaryTree::visualTree()//可视化树
{
    leaf[v[0]]->x=0;
    //调整横坐标,上一个结点的横坐标(左端点)加上上一个结点的长度,加上两个括号和两个空格
    for (int i=1; i<v.size(); i++) leaf[v[i]]->x=leaf[v[i-1]]->x+(int)log10(leaf[v[i-1]]->element)+1+4;
    int nowlevel=0;//记录当前结点的层次,从0开始
    int nowx=0;//记录当前结点前面输出了多少个字符,便于此层输出
    while(!q.empty()){//层次遍历确定横坐标
        binaryTreeNode* tempnode=q.front();
        if(tempnode->y!=nowlevel){//进入了下一层
            putchar('\n'); nowlevel++; nowx=0;
            //注意,这里后面要输出上下的链接符号:'|'
            queue<binaryTreeNode* > q2; putchar(' ');
            while(!q.empty()){
                binaryTreeNode* tempnode2=q.front(); q.pop(); q2.push(tempnode2);
                //当前层横坐标微调
                int tempx=tempnode2->x+ceil(((double)(int)log10(tempnode2->element)+1)/2);
                for (int i=1; i<=tempx-nowx-1; i++) putchar(' ');
                putchar('|'); nowx=tempx;
            }
            while(!q2.empty()){ q.push(q2.front()); q2.pop(); }
            nowx=0; putchar('\n');
        }
        q.pop();
        //当前层输出,___(xxxx)___结构
        if(tempnode->leftChild!=nullptr){
            int templeftx=tempnode->leftChild->x+ceil(((double)(int)log10(tempnode->leftChild->element)+1)/2);
            //int tempx=tempnode->x+ceil(((double)(int)log10(tempnode->x)+1)/2);
            for (int i=1; i<=templeftx-nowx+1; i++) putchar(' ');
            for (int i=1; i<=tempnode->x-templeftx-1; i++) putchar('_');
            q.push(tempnode->leftChild);
        }
        else {
            for (int i=1; i<=tempnode->x-nowx; i++) putchar(' ');
        }
        printf("(%d)",tempnode->element);
        if(tempnode->rightChild!=nullptr){
            int temprightx=tempnode->rightChild->x+ceil(((double)(int)log10(tempnode->rightChild->element)+1)/2);
            for (int i=1; i<=temprightx-(tempnode->x+(int)log10(tempnode->element)+2)-1; i++) putchar('_');
            nowx=temprightx; q.push(tempnode->rightChild);
        }
        else nowx=tempnode->x+(int)log10(tempnode->element)+3;
    }
}
void linkedBinaryTree::visual_binaryTree()
{
    inorder(root);
    while(!q.empty()) q.pop();
    q.push(root);
    visualTree();
    putchar('\n');
    v.clear();
}
void linkedBinaryTree::copy1(binaryTreeNode *node)
{
    if(node!=nullptr){
    if(leaf[node->element]==nullptr) leaf[node->element]=node;
        copy1(node->leftChild);
        copy1(node->rightChild);
    }
}
void linkedBinaryTree::from_forest(binaryTreeNode *t)
{
    root=t;
    copy1(root);
}
binaryTreeNode* linkedBinaryTree::binaryTree_to_forest()
{
    if(root->element!=0){//如果是一棵崭新的二叉树
        leaf[0]=new binaryTreeNode(0);//新建立一个0号结点
        leaf[0]->leftChild=root;
        root=nullptr;
    }
    return leaf[0];
}
bool linkedBinaryTree::insert(int father, int node, int lr)
{
    if(leaf[father]==nullptr) leaf[father]=new binaryTreeNode(father);
    leaf[node]=new binaryTreeNode(node);
    if(lr) {
        if(leaf[father]->leftChild==nullptr)
            leaf[father]->leftChild=leaf[node];
        else return false;
    }
    else {
        if(leaf[father]->rightChild==nullptr)
            leaf[father]->rightChild=leaf[node];
        else return false;
    }
    return true;
}
void linkedBinaryTree::insert_l_r(int father, int left, int right)
{
    if(leaf[father]==nullptr) leaf[father]=new binaryTreeNode(father);
    if(left!=-1) {
        if(leaf[left]==nullptr) leaf[left]=new binaryTreeNode(left);
        leaf[father]->leftChild=leaf[left];
    }
    if(right!=-1){
        if(leaf[right]==nullptr) leaf[right]=new binaryTreeNode(right);
        leaf[father]->rightChild=leaf[right];
    }
}
int linkedBinaryTree::showTheBinaryTree(binaryTreeNode *t)
{
    int ans=0;
    preorder(t,ans);
    return ans;
}
void linkedBinaryTree::preorder(binaryTreeNode *t, int &ans)
{
    if(t!=nullptr){
        ans^=t->element;
        preorder(t->leftChild,ans);
        preorder(t->rightChild,ans);
    }
}
void linkedBinaryTree::output(binaryTreeNode *t)
{
    if(t!=nullptr){
        cout<<t->element<<' ';
        if(t->leftChild!=nullptr) cout<<t->leftChild->element<<' ';
        else cout<<-1<<' ';
        if(t->rightChild!=nullptr) cout<<t->rightChild->element<<endl;
        else cout<<-1<<endl;
        output(t->leftChild);
        output(t->rightChild);
    }
}
class Forest : public linkedBinaryTree//派生森林类
{
public:
    ~Forest(){
        for (int i=0; i<maxn; i++)
            if(leaf[i]!=nullptr && leaf[i]->element==i)
                delete leaf[i];
        delete[] leaf;
    };
    void visual_forest(int m);
    void insert(int father,int node);
    void init(int size,int *a);
    bool erase(int father,int node);
    void showTheForest();
    bool link(int first,int second);
    binaryTreeNode* forest_to_binaryTree();
    void from_binaryTree(binaryTreeNode* t);
};
void Forest::visual_forest(int m)
{
    while(!q.empty()) q.pop();
    binaryTreeNode* tempnode=root->leftChild;
    binaryTreeNode* temprightChild[m];//暂存根的右兄弟

    while(tempnode!=nullptr){//都是根结点
        tempnode->y=0;
        if(tempnode->leftChild!=nullptr) {
            tempnode->leftChild->y=1;
            inorder(tempnode->leftChild);
        }
        v.push_back(tempnode->element);
        tempnode=tempnode->rightChild;
    }
    tempnode=root->leftChild;
    while(tempnode!=nullptr){
        q.push(tempnode);
        tempnode=tempnode->rightChild;
    }
    tempnode=root->leftChild;
    int cnt=0;
    while(tempnode->rightChild!=nullptr){
        temprightChild[++cnt]=tempnode->rightChild;
        tempnode->rightChild=nullptr;
        tempnode=temprightChild[cnt];
    }
    visualTree();
    if(cnt!=0) root->leftChild->rightChild=temprightChild[1];
    for (int i=1; i<cnt; i++){
        temprightChild[i]->rightChild=temprightChild[i+1];
    }
    putchar('\n');
    v.clear();
}
void Forest::from_binaryTree(binaryTreeNode *t)//根据大小重新链接各个根结点
{
    root=t;
    copy1(root);
    binaryTreeNode* tempgrandson=nullptr;
    binaryTreeNode* tempnode=root->leftChild;
    if(tempnode!=nullptr && tempnode->rightChild!=nullptr){
        tempgrandson=tempnode->rightChild;
        tempnode->rightChild=nullptr;
        while(tempgrandson!=nullptr){
            tempnode=tempgrandson;
            tempgrandson=tempgrandson->rightChild;
            tempnode->rightChild=nullptr;
            Forest::insert(0,tempnode->element);
        }
    }
}
binaryTreeNode* Forest::forest_to_binaryTree()
{
    binaryTreeNode* temp=root;
    root=nullptr;
    return temp->leftChild;
}
void Forest::showTheForest()
{
    binaryTreeNode* templeaf=root->leftChild;
    while(templeaf!=nullptr){
        int temp=showTheBinaryTree(templeaf->leftChild)^templeaf->element;
        cout<<temp<<' ';
        templeaf=templeaf->rightChild;
    }
}
bool Forest::erase(int father,int node)
{
    if(father==-1) father=0;//删除根结点
    binaryTreeNode* tempnode=leaf[father]->leftChild;//初始化为father的大儿子,最终存储为要删除的结点
    binaryTreeNode* tempgrandson=nullptr;
    if(leaf[father]->leftChild==nullptr){//如果要删除的父亲点没有儿子,即node不存在
        return false;//删除失败
    }
    if(leaf[father]->leftChild->element==node){//删除的是大儿子
        binaryTreeNode* tempnode2=leaf[father]->leftChild;
        leaf[father]->leftChild=tempnode->rightChild;
        tempnode=tempnode2;
    }
    else {//删除的不是大儿子
        while(tempnode->rightChild!=nullptr && tempnode->rightChild->element!=node)
            tempnode=tempnode->rightChild;
        if(tempnode->rightChild==nullptr){//找不到,删除失败
            return false;
        }
        //tempnode->rightChild是要删除的结点
        binaryTreeNode* tempnode2=tempnode->rightChild;
        tempnode->rightChild=tempnode->rightChild->rightChild;
        tempnode=tempnode2;
    }
    //tempnode->leftChild这一串将要都成为新的树,tempnode是要删除的点
    binaryTreeNode* tempnewnode=tempnode;
    if(tempnode->leftChild!=nullptr){
        tempgrandson=tempnode->leftChild->rightChild;
        tempnode->leftChild->rightChild=nullptr;
        Forest::insert(0,tempnode->leftChild->element);
        while(tempgrandson!=nullptr){
            tempnode=tempgrandson;
            tempgrandson=tempgrandson->rightChild;
            tempnode->rightChild=nullptr;
            Forest::insert(0,tempnode->element);
        }
    }
    delete tempnewnode;
    return true;

}
void Forest::insert(int father, int node)
{
    if(leaf[father]==nullptr) leaf[father]=new binaryTreeNode(father);
    if(leaf[node]==nullptr) leaf[node]=new binaryTreeNode(node);//开新结点
    if(father==-1) father=0;
    if(leaf[father]->leftChild==nullptr) leaf[father]->leftChild=leaf[node];//左儿子还有空位置
    else {//已经有一个儿子了,剩下的需要化作father左儿子的右兄弟
        binaryTreeNode* templeaf=leaf[father]->leftChild;
        if(templeaf->element>node){//插入大儿子
            leaf[father]->leftChild=leaf[node];
            leaf[node]->rightChild=templeaf;
        }
        else {//不是大儿子
            while(templeaf->rightChild!=nullptr && templeaf->rightChild->element<node)
                templeaf=templeaf->rightChild;
            binaryTreeNode* templeaf2=templeaf->rightChild;
            templeaf->rightChild=leaf[node];
            leaf[node]->rightChild=templeaf2;
        }
    }
}
void Forest::init(int size, int *a)//初始化森林
{
    sort(a+1,a+size+1,greater<int>());//从大到小排序,每次插入更快
    leaf[0]=new binaryTreeNode(0);//森林的根设置为0
    root=leaf[0];
    for (int i=1; i<=size; i++)
        Forest::insert(0,a[i]);
}
bool Forest::link(int first, int second)
{
    binaryTreeNode* tempfirstleaf=root->leftChild;
    binaryTreeNode* tempsecondleaf=root->leftChild;
    //先找到first
    if(tempfirstleaf->element!=first){
        while(tempfirstleaf->rightChild!=nullptr && tempfirstleaf->rightChild->element!=first)
            tempfirstleaf=tempfirstleaf->rightChild;
        if(tempfirstleaf->rightChild==nullptr)//找不到first
            return false;
        tempfirstleaf=tempfirstleaf->rightChild;
    }
    //此时找到了first,开始找second,并断开联系
    if(tempsecondleaf->element==second){//大儿子就是second
        root->leftChild=root->leftChild->rightChild;
        tempsecondleaf->rightChild=nullptr;
    }
    else{
        while(tempsecondleaf->rightChild!=nullptr && tempsecondleaf->rightChild->element!=second)
            tempsecondleaf=tempsecondleaf->rightChild;
        if(tempsecondleaf->rightChild==nullptr) //找不到second
            return false;
        binaryTreeNode * tempnode2=tempsecondleaf->rightChild;
        tempsecondleaf->rightChild=tempsecondleaf->rightChild->rightChild;
        tempsecondleaf=tempnode2;
        tempsecondleaf->rightChild=nullptr;
    }
    Forest::insert(tempfirstleaf->element,tempsecondleaf->element);
    return true;
}
void outputplus(int k,linkedBinaryTree bt,Forest ft)
{
    cout<<"Show:"<<endl;
    if(k) bt.output(bt.getTheRoot());
    else ft.output(ft.getTheRoot());
    cout<<"End"<<endl;
}
void welcome()
{
    cout<<"-----------------------------------------------------------------————————————————————-"<<endl;
    cout<<"|                         欢迎使用森林与二叉树实验演示程序                                |"<<endl;
    cout<<"|                                 author:TZL                                         |"<<endl;
    cout<<"|                                                                                    |"<<endl;
    cout<<"|                                                                                    |"<<endl;
    cout<<"|功能介绍:本程序可以实现二叉树与森林的初始构造,实现森林的插入,删除,合并操作,二叉树的插入操作,|"<<endl;
    cout<<"|        以及森林与二叉树的转换,森林的二叉树结构展示,二叉树展示功能                         |"<<endl;
    cout<<"|                                                                                    |"<<endl;
    cout<<"-----------------------------------------------------------------————————————————————-"<<endl;
}
void init(int &k,int &m,int &n,linkedBinaryTree &binaryTree_temp,Forest &forest_temp,int* a)
{
    cout<<"请问您想构造(0.森林 1.二叉树):"; cin>>k; cout<<endl;
    cout<<"请输入初始化的结点数:"; cin>>n; cout<<endl;
    if(k==0){//森林
        cout<<"请问您想构建几颗树:";cin>>m; cout<<endl;
        cout<<"请输入这些树根结点的编号:"; for (int i=1; i<=m; i++) cin>>a[i];
        cout<<endl; forest_temp.init(m,a);
        cout<<"请输入n行结点的父子信息,n为结点个数,信息格式为:A B [nodes], 表示结点 A 拥有 B 个孩子结点, "<<endl;
        cout<<"孩子结点的集合为 nodes,例如 1 2 3 4 表示结点 1 拥有 2 个孩子, 分别为结点 3, 4。"<<endl;
        for (int i=1; i<=n; i++){
            int A,B; cin>>A>>B;
            for (int j=1; j<=B; j++){
                int x; cin>>x;
                forest_temp.insert(A,x);
            }
        }
        cout<<"初始化完成,当前结构如下:"<<endl;
        cout<<"注:森林中树结构使用的孩子兄弟表示法来演示"<<endl;
        forest_temp.visual_forest(m);

    }
    else {//二叉树
        m=1; int root;
        cout<<"请输入根结点的编号:"; cin>>root;
        cout<<endl; binaryTree_temp.init(root);
        cout<<"请输入n行结点的父子信息,n为结点个数,信息格式为:A l r, 表示结点 A 的左孩子是 l, 右孩子是 r, 若是某个孩子不存在, 则其为值为 -1。"<<endl;
        for (int i=1; i<=n; i++){
            int A,l,r; cin>>A>>l>>r;
            binaryTree_temp.insert_l_r(A,l,r);
        }
        cout<<"初始化完成,当前结构如下:"<<endl;
        binaryTree_temp.visual_binaryTree();
    }
}
void solve(Forest &forest_temp,linkedBinaryTree &binaryTree_temp,int &m,int &k)
{
    cout<<"下面输入您想要的操作,操作格式如下:"<<endl;
    putchar('\n');
    cout<<"0 退出程序"<<endl;
    putchar('\n');
    cout<<"1 father node 表示为森林中树的结点 father 插入一个孩子结点 node ,若 father 为 -1 , 表示插入的是孤立结点。"<<endl;
    cout<<"注意同一父亲的孩子从左至右按大小升序保存。"<<endl;
    putchar('\n');
    cout<<"2 father node 表示删除森林中的结点 node , 其中 father 是 node 的父亲结点,father 若为 -1 ,代表删除根结点。"<<endl;
    cout<<"若待删除的结点 node 有孩子, 则其所有孩子结点在删除后成为新的树, 保留其原有的子树结构。"<<endl;
    putchar('\n');
    cout<<"3 a b 表示在森林中的根结点 a, b 间插入一条边, 其中 a 为 b 结点的父亲。"<<endl;
    putchar('\n');
    cout<<"4 森林、二叉树转换, 若当前为森林,则将森林转为二叉树,若当前为二叉树,则将二叉树转为森林。当森林转换二叉树时, "<<endl;
    cout<<"将编号最小的根结点作为合并后的根结点, 其余根结点按从小到大合并。二叉树转森林时,无须恢复原有的树结构。"<<endl;
    putchar('\n');
    cout<<"5 pos father node 表示为二叉树的 father 结点插入一个孩子 node , pos 的范围为{0, 1}, 0 表示插入的是 右孩子,"<<endl;
    cout<<"1 表示插入的是 左孩子 . 数据保证 father 待插入的位置没有孩子。"<<endl;
    putchar('\n');
    cout<<"6 显示森林/二叉树。显示二叉树时,输出一行二叉树的前序遍历序列的异或值。显示森林时,按森林根大小的顺序升序输出一"<<endl;
    cout<<"行森林中各棵树的结点遍历序列的异或值,元素间用空格分隔。"<<endl;
    putchar('\n');
    cout<<"7 图形化显示森林/二叉树"<<endl;
    putchar('\n');
    cout<<"请输入操作:";
    while(true){
        int op; cin>>op;
        if(op==0){
            cout<<"谢谢使用,再见!"<<endl;
            break;
        }
        else if(op==1){//为森林中树的结点father插入一个孩子结点node,若father为-1, 表示插入的是孤立结
            int father,node; cin>>father>>node;
            forest_temp.insert(father,node);
            cout<<"插入成功!"<<endl;
        }
        else if(op==2){//删除森林中的结点node, 其中father是node的父亲结点,father若为-1,代表删除根结点
            int father,node; cin>>father>>node;
            if(!forest_temp.erase(father,node)){
                cout<<"删除失败,"<<father<<"号结点不存在"<<node<<"号孩子!"<<endl;
            }
            else cout<<"删除成功!"<<endl;
        }
        else if(op==3){//在森林中的根结点 a, b 间插入一条边, 其中 a 为 b 结点的父亲
            int aa,b; cin>>aa>>b;
            forest_temp.link(aa,b);
            cout<<"连接成功!当前森林结构变为下图:"<<endl;
            forest_temp.visual_forest(m);
        }
        else if(op==4){//森林<->二叉树转换
            if(k) {//二叉树转化为森林
                k=0; forest_temp.from_binaryTree(binaryTree_temp.binaryTree_to_forest());
                cout<<"转化完成,当前结构为森林。"<<endl;
            }
            else {//森林转化为二叉树
                k=1; binaryTree_temp.from_forest(forest_temp.forest_to_binaryTree());
                cout<<"转化完成,当前结构为二叉树。"<<endl;
            }
        }
        else if(op==5){//为二叉树的father结点插入一个孩子node, pos的范围为{0, 1}, 0 表示插入的是左孩子, 1 表示插入的是右孩子
            int father,pos,node; cin>>pos>>father>>node;
            if(!binaryTree_temp.insert(father,node,pos)){
                cout<<"插入失败,当前结点已经有";
                if(pos) cout<<"右";
                else cout<<"左";
                cout<<"孩子"<<endl;
            }
            else cout<<"插入成功"<<endl;
        }
        else if(op==6){//显示森林/二叉树
            if(k) {
                cout<<"二叉树全部结点遍历后的异或值为:"<<binaryTree_temp.showTheBinaryTree(binaryTree_temp.getTheRoot());
            }
            else {
                cout<<"森林各个树结构遍历后的结点异或值为:";
                forest_temp.showTheForest();
            }
            putchar('\n');
        }
        else if(op==7){
            if(k) {
                cout<<"当前二叉树结构如下:"<<endl;
                binaryTree_temp.visual_binaryTree();
            }
            else {
                cout<<"当前森林中各个树使用孩子兄弟表示法如下:"<<endl;
                forest_temp.visual_forest(m);
            }
        }
        cout<<"请继续输入操作:";
    }
}
int main()
{
    int K,M,N,a[5001];
    linkedBinaryTree binaryTree;
    Forest forest;

    welcome();
    init(K,M,N,binaryTree,forest,a);
    solve(forest,binaryTree,M,K);

    return 0;
}
/*
0 2 10
1 5
1 3 2 3 4
2 0
3 0
4 0
5 2 6 7
6 3 8 9 10
7 0
8 0
9 0
10 0
3
6
4
6

1 1 9
1
1 -1 2
2 3 4
3 7 -1
4 5 6
5 -1 8
6 -1 9
7 -1 -1
8 -1 -1
9 -1 -1
3
6
4
6
 */

部分操作在控制台中的输出结果如下:

-----------------------------------------------------------------————————————————————-
|                         欢迎使用森林与二叉树实验演示程序                                |
|                                 author:TZL                                         |
|                                                                                    |
|                                                                                    |
|功能介绍:本程序可以实现二叉树与森林的初始构造,实现森林的插入,删除,合并操作,二叉树的插入操作,|
|        以及森林与二叉树的转换,森林的二叉树结构展示,二叉树展示功能                         |
|                                                                                    |
-----------------------------------------------------------------————————————————————-
请问您想构造(0.森林 1.二叉树)0

请输入初始化的结点数:10

请问您想构建几颗树:2

请输入这些树根结点的编号:6 10

请输入n行结点的父子信息,n为结点个数,信息格式为:A B [nodes], 表示结点 A 拥有 B 个孩子结点, 
孩子结点的集合为 nodes,例如 1 2 3 4 表示结点 1 拥有 2 个孩子, 分别为结点 3, 46 0
10 3 2 8 5
2 1 9
8 0
5 3 4 3 1
4 0
9 0
3 1 7
7 0
1 0
初始化完成,当前结构如下:
注:森林中树结构使用的孩子兄弟表示法来演示
(6)         _________________________________(10)
           |
       ___(2)_______________________
      |                             |
     (9)         __________________(5)___
                |                        |
               (1)________              (8)
                          |
                      ___(3)___
                     |         |
                    (7)       (4)
下面输入您想要的操作,操作格式如下:

0 退出程序

1 father node 表示为森林中树的结点 father 插入一个孩子结点 node ,若 father 为 -1 , 表示插入的是孤立结点。
注意同一父亲的孩子从左至右按大小升序保存。

2 father node 表示删除森林中的结点 node , 其中 father 是 node 的父亲结点,father 若为 -1 ,代表删除根结点。
若待删除的结点 node 有孩子, 则其所有孩子结点在删除后成为新的树, 保留其原有的子树结构。

3 a b 表示在森林中的根结点 a, b 间插入一条边, 其中 a 为 b 结点的父亲。

4 森林、二叉树转换, 若当前为森林,则将森林转为二叉树,若当前为二叉树,则将二叉树转为森林。当森林转换二叉树时, 
将编号最小的根结点作为合并后的根结点, 其余根结点按从小到大合并。二叉树转森林时,无须恢复原有的树结构。

5 pos father node 表示为二叉树的 father 结点插入一个孩子 node , pos 的范围为{0, 1}, 0 表示插入的是 右孩子,
1 表示插入的是 左孩子 . 数据保证 father 待插入的位置没有孩子。

6 显示森林/二叉树。显示二叉树时,输出一行二叉树的前序遍历序列的异或值。显示森林时,按森林根大小的顺序升序输出一
行森林中各棵树的结点遍历序列的异或值,元素间用空格分隔。

7 图形化显示森林/二叉树

请输入操作:1 -1 11
插入成功!
请继续输入操作:1 11 12
插入成功!
请继续输入操作:1 6 13
插入成功!
请继续输入操作:7
当前森林中各个树使用孩子兄弟表示法如下:
  ____(6)         _________________________________(10)    ____(11)
 |               |                                        |
(13)         ___(2)_______________________               (12)
            |                             |
           (9)         __________________(5)___
                      |                        |
                     (1)________              (8)
                                |
                            ___(3)___
                           |         |
                          (7)       (4)
请继续输入操作:2 10 5
删除成功!
请继续输入操作:7
当前森林中各个树使用孩子兄弟表示法如下:
(1)    ___(3)  (4)    ____(6)         ________(10)    ____(11)
      |              |               |               |
     (7)            (13)         ___(2)___          (12)
                                |         |
                               (9)       (8)
请继续输入操作:3 6 10
连接成功!当前森林结构变为下图:
(1)    ___(3)  (4)                   __________(6)    ____(11)
      |                             |                |
     (7)                   ________(10)___          (12)
                          |               |
                      ___(2)___          (13)
                     |         |
                    (9)       (8)
请继续输入操作:4
转化完成,当前结构为二叉树。
请继续输入操作:7
当前二叉树结构如下:
(1)________
           |
       ___(3)___
      |         |
     (7)       (4)______________________________
                                                |
                                     __________(6)_________
                                    |                      |
                           ________(10)___            ____(11)
                          |               |          |
                      ___(2)___          (13)       (12)
                     |         |
                    (9)       (8)
请继续输入操作:0
谢谢使用,再见!
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值