如何使用命令行进行虚假的可视化
题目见我的另一篇博客:传送门
本文是这篇博客的可视化版本,使用命令行可视化,能够实现森林中各个树的孩子兄弟表示法可视化以及二叉树可视化,截图如下:
可视化操作涉及到的函数主要是:
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, 4。
6 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
谢谢使用,再见!