二叉树的字符图形显示程序
实验内容及要求:
设二叉树采用二叉链表存储结构,结点数据域为字符类型。编写控制台应用程序采用先序遍历法建立二叉树存储结构并实现二叉树的字符图形显示。输入及输出示例如下:
输入: ABDH##I##EJ##K##CFL##M##GN##O##¿ (#表示NULL指针域,¿表示回车键)
输出:
A 行1
________|________ 行2 横线由至少2个下划线字符组成,竖线是一个|字符
| | 行3
B C 行4
____|____ ____|____ 行5
| | | | 行6
D E F G 行7
__|__ __|__ __|__ __|__ 行8 (行8的每根水平线由2个下划线字符组成)
| | | | | | | | 行9
H I J K L M N O 行10
输入: A#B#C##¿
输出:
A
|____
|
B
|__
|
C
输入: AB#DE##F##CG###¿
输出:
A
________|________
| |
B C
|____ ____|
| |
D G
__|__
| |
E F
输入: AB##C##¿
输出:
A
__|__
| |
B C
实验目的:对于二叉树(二叉链表)存储结构,综合运用所学知识,通过分析及算法设计解决课堂及教材未讲过的问题。
#include<iostream>
#include <conio.h>
#include<fstream>
#include<iomanip>
#include<Windows.h>
#include<math.h>
using namespace std;
int depth;//数的总层数
int countnode = 0;//节点计数器
typedef struct Tree
{
char e;
Tree* lchild;
Tree* rchild;
Tree* parent;
}T;//二叉树三叉链表
void goto_xy(int x, int y)
{
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x,y };
SetConsoleCursorPosition(hOut, pos);
}//从网上找到的移动光标函数
void PrintfSpace()
{
goto_xy(0, 20);
for(int i =0;i<15;i++)
for (int j = 0; j < 80; j++)
{
cout << " ";
}
}//打印大量空格,防止二叉树图形和程序运行完后控制台显示的字重合
T* CreatTree(T* bt, char* temp)//先序建立二叉树
{
static int i = 0;
char c;
if ((c = temp[i++]) == '#')//括号很重要,因为==的优先级大于赋值运算符
return 0;
else
{
bt = new T;
countnode++;
bt->e = c;
bt->lchild = CreatTree(bt->lchild, temp);
bt->rchild = CreatTree(bt->rchild, temp);
return bt;
}
}
void PreorderII(T* bt)
{
if (!bt)return;
else
{
cout << bt->e << " ";
PreorderII(bt->lchild);
PreorderII(bt->rchild);
}
}//前序遍历
void PrintH(int n)
{
for (int i = 0; i < n; i++)
{
cout << '_';
}
}//打印指定数量的下划线
int CountDepth(T* bt)
{
int hl, hr;
if (!bt)
return 0;
hl = CountDepth(bt->lchild);
hr = CountDepth(bt->rchild);
return max(hl,hr)+1;
}//计算树的深度来确认横线的长短
void Display(T* bt, int k, int distance, int j)//根节点bt,层号k,横坐标distance,行号j,左右儿子标志flag
{
if (!bt)return;
goto_xy(distance, j);
cout << bt->e;
int offset = 2 << (depth - k);//左右儿子相对于根节点的偏移量
j++;
if (bt->lchild)
{
goto_xy(distance - offset, j);
PrintH(offset);
goto_xy(distance - offset, j + 1);
cout << "|";
}
if (bt->rchild)
{
goto_xy(distance + 1, j);
PrintH(offset);
goto_xy(distance + offset, j + 1);
cout << "|";
}
if (bt->lchild || bt->rchild)
{
goto_xy(distance, j);
cout << "|";
}
//打印左右两边的下划线以及中间的竖线
j++;//打印完进入下一行
Display(bt->lchild, k+1, distance - offset, j + 1);
Display(bt->rchild, k+1, distance + offset, j + 1);
//递归打印左右子树
return;
}
int main(void)
{
char temp[1024] = { 0 };
cin >> temp;
T* bt = 0;
bt = CreatTree(bt, temp);
PreorderII(bt);
depth = CountDepth(bt);
Display(bt, 1, 60, 0);//起始横坐标为(60,0)
PrintfSpace();
return 0;
}