#include<iostream>
#include<cmath>
using namespace std;

static int figure=0;//所含结点个数
char result[100]={0};//记录层次遍历的结果
//class QNode{};  //队列结点
//class BTree{};
//class LinkQueue{};//队列

class BTreeNode{ //二叉树结点
 char data;
 BTreeNode* lchild; //左孩子
 BTreeNode* rchild; //右孩子
public:
 BTreeNode(char& e,BTreeNode* l=NULL,BTreeNode* r=NULL){
  data=e;
  lchild=l;
  rchild=r;
 }
 friend class QNode;
 friend class BTree;
};
BTreeNode* t_temp;

class QNode{ //队列结点,结点的数据为:1。指向二叉树结点的指针,2。指向队列的下一个节点。
 BTreeNode* node;
 QNode* next;
public:
 QNode(BTreeNode* t=NULL){
  node=t;
  next=NULL;
 }
 friend class LinkQueue;
};

 

class LinkQueue{ //队列
 QNode* front; //队列头指针
 QNode* rear; //队列尾指针
public:
 LinkQueue(){  //队列构造:头指针、尾指针指向一个新建的结点,结点为空
  rear=front=new QNode();
 }
 void InQueue(BTreeNode* item){   //入队列
  rear->next=new QNode(item);  //队尾的下一个结点指针,指向新建的队列结点,新建的结点存是要入队的指向树结点的指针
  rear=rear->next;      //队尾指指针指向最后一个结点
 }
 BTreeNode* OutQueue(){             //出队列
  QNode* p;
  p=front->next;//p指向第一个有数据的结点
  //BTreeNode* t_temp
  t_temp=p->node;//临时变量,存储p中的结点
  front->next=p->next;//修改头结点的指针域
  delete p;
  if(!front->next) rear=front;//此时队列只有一个尾结点时,rear被删,需要重新指向。
  return t_temp;
 }
};

class BTree{
public:
 void CreateBTree(BTreeNode*&);//建立二叉树
 void InOrder(BTreeNode*&);//中序遍历
 void DrawTree(BTreeNode*&);//画二叉树
 int Height(BTreeNode*&);
};
void BTree::CreateBTree(BTreeNode*& t)//建立二叉树
{
 char u;
 cin>>u;
 if(u=='*'){//遇'*'则不建立结点????
  figure++;
  t=NULL;
 }
 else{
  t=new BTreeNode(u);
  figure++;
  cout<<"生成了一个节点\n";
  CreateBTree(t->lchild);//生成当前结点的左孩子
  CreateBTree(t->rchild);//生成当前节点的右孩子
 }
}

void BTree::InOrder(BTreeNode*& t){ //中序遍历二叉树
 if(t){
  InOrder(t->lchild);
  cout<<t->data<<" ";
  InOrder(t->rchild);
 }
}

void BTree::DrawTree(BTreeNode*& t){ //画二叉树
 char c='*';
 LinkQueue queue;//遍历时用于存储
 BTreeNode* q=new BTreeNode(c);
 BTreeNode* p=t;//t为传递过来的根结点指针
 if(p) queue.InQueue(p);
 for(int i=0;i<figure;i++)//通过队列中序遍历
 {
  p=queue.OutQueue();//出队列
  result[i]=p->data;
  if(p->data){
   if(p->lchild) queue.InQueue(p->lchild);
   else queue.InQueue(q);
   if(p->rchild) queue.InQueue(p->rchild);
   else queue.InQueue(q);
  }
 }
}

int BTree::Height(BTreeNode*& t){ //计算二叉树高度
 if(!t) return 0;
 int hl,hr;
 hl=Height(t->lchild);
 hr=Height(t->rchild);
 return hl>hr?++hl:++hr;
}

int main(){
 int h=0;//高度
 int times=1;//层次
 int r=0;
 BTree bt;
 BTreeNode* root=NULL;
 cout<<"输入二叉树各结点的值,'*'表示遇到空指针:"<<endl;
 bt.CreateBTree(root);
 if(!root) cout<<"空二叉树!"<<endl;
 else{
  cout<<"中序遍历结果输出:"<<endl;
  bt.InOrder(root);
  cout<<"\n画出二叉树:"<<endl;
  h=bt.Height(root);
  bt.DrawTree(root);
  while(times<=h){ //控制输出
   for(int i=0;i<pow(2.0,h-times);i++) //pow
    cout<<" ";//控制每行开头的空格
   for(int j=0;j<pow(2.0,times-1);j++,r++)
   {
    if(result[r]!='*') cout<<result[r];
    else cout<<" ";
    for(int k=0;k<pow(2.0,h-times+1)-1;k++)
     cout<<" ";//每行内部空格
   }
   cout<<endl;
   times++;
  }
 }
 system("pause");
 return 0;
}