本段代码的功能包括:
1、用不同的前序遍历创建二叉树。
2、分别用递归或借助栈实现二叉树的前、中、后序遍历。
3、二叉树的深度、广度遍历。
4、判断一棵树是否是完全二叉树、满二叉树
5、用不同方法求所有根结点到树叶的路径、树叶到根结点的路径
6、求树的树宽、树深(树高)
7、求树的最长路径
8、输出所有叶子结点
9、计算二叉树零度、一度、二度结点的数量
10、将数的中缀表达式转化为后缀表达示,并求解树的中缀表达式
/*
测试树:
ABC00DE0G00F00H..
ABS00C00DE00FG0H00I00
ABD00E00CF000 完全二叉树 ABD00E00CF00G00满二叉树
abcd00e00f00ig00h00
abd00e00cf00g00
123-1-14-1-156-1-18-1-1
1 2 3 0 0 5 0 0 6 7 0 0 9 0 0
*/
#include<iostream>
#include<stack>
#include<queue>
#define OK 1
#define maxsize 100
using namespace std;
//定义一棵树的结构体包括根结点、左孩子,右孩子(字符树)
typedef struct Tnode {
char data;
string combine_data; //结点数据域(数值,可大于9),用于树的表达式求值
struct Tnode* lchild, * rchild;
}*Btree;
//数字树
typedef struct node {
int data;
struct node* lchild, * rchild;
}*Bntree;
void Instruct_char(Btree T);
void Create_Tree(Btree T);
void Calculate_Tree(Btree T);
void Traverse(Btree T);
void Estimate(Btree T);
void Path(Btree T);
void Calculate_Node(Btree T);
void Swap_child(Btree T);
void Build(Btree& T);
void CreateTree(Btree& T, char ch[], int& index);
int Tree_Width_recursion(Btree T);
int Tree_Width(Btree T);
int Tree_Depth_recursion(Btree T);
int Tree_Depth(Btree T);
void PreOrder(Btree T);
void PreOrder_recursion(Btree T);
void InOrder(Btree T);
void InOrder_recursion(Btree T);
void PostOrder(Btree T);
void PostOrder_recursion(Btree T);
void postOrder_visit(Btree T);
void Breadth_First_Search(Btree T);
void Depth_First_Search(Btree T);
void Sequence_traverse(Btree T);
void Depth_First_Search(Btree T);
bool isComplete_Tree(Btree T);
bool isFullBinaryTree(Btree T);
void Every_path_recursion(Btree T, char E_path[], int len);
void AllPath(Btree T);
void All_path_root_leaf(Btree T, int pos);
void One_Longest_Path(Btree T);
void Find_First_Longest_Path(Btree T);
void Print_First_Longest_Path(Btree T);
void Sum_node(Btree T, int& zero, int& one, int& two);
int getAllNode(Btree T);
void PrintLeaves(Btree T);
void swap(Btree& T1, Btree& T2);
void Node_Swap(Btree& T);
void Clear();
Btree Inquire_node(Btree T, char n);
Bntree Create_Number_Tree();
void Instruct_number();
void CreateBiTree(Bntree* T);
void Index();
void Func();
int main()
{
Btree T = nullptr;
Bntree T1 = nullptr;
Index();
return 0;
}
void Clear()
{
cin.clear();
cin.ignore(1, EOF);
cout << endl;
system("cls");//清屏函数
}
void Index()
{
Btree T=nullptr;
int choice = 0;
cout << "请选择:\n1、字符树\n2、数字树\n3、树的中缀表达式求值\n";
while (cin >> choice && choice != 0)
{
switch (choice)
{
case 1:Instruct_char(T); break;
case 2:Instruct_number(); break;
case 3:Func(); break;
default:cout << "输错啦,请重新输入..." << endl;
}
}
}
void Instruct_number()
{
Bntree T;
int choice = 0;
cout << "请选择:\n1、“-1为空的树创建\n2、以零为空的树的创建\n3、返回主菜单\n";
while (cin >> choice)
{
switch (choice)
{
case 1:Create_Number_Tree(); cout << "创建成功" << endl; Index();
case 2:CreateBiTree(&T); cout << "创建成功" << endl; Index();
case 3:Index(); break;
default:cout << "输错啦,请重新输入..." << endl;
}
}
}
void Instruct_char(Btree T)
{
int choice = 0;
Clear();
cout << "-------------------------欢迎来到树专题学习栏目-------------------\n";
printf("请选择你想要的操作\n1、创建二叉树\n2、求树高树宽\n3、遍历输出\n4、关于树的判断\n5、\n6、路径查询\n7、求解各种结点数量\n8、交换左右孩子\n、返回主菜单");
while (cin >> choice && choice != 0)
{
switch (choice)
{
case 1:Create_Tree(T); break;
case 2:Calculate_Tree(T); break;
case 3:Traverse(T); break;
case 4:Estimate(T); break;
case 6:Path(T); break;
case 7:Calculate_Node(T); break;
case 8:Swap_child(T); break;
default:cout << "输错啦,请重新输入...\n" << endl;
break;
}
}
Clear();
}
void Create_Tree(Btree T)
{
int choice = 0;
char ch[maxsize];
int index = 0;
Clear();
printf("请选择您想要进行的操作\n1、前序创建树之char数组法\n2、直接用char\n3、前序创建数字树(用-1区分是否为空)\n4、创建数字树(用0区分是否为空)\n");
while (cin >> choice && choice != 0)
{
cout << "请输入前序遍历的树字符串" << endl;
switch (choice)
{
case 1: Build(T); cout << "创建成功" << endl; Instruct_char(T);
case 2:CreateTree(T, ch, index); cout << "创建成功" << endl; Instruct_char(T);
case 3: Create_Number_Tree(); cout << "创建成功" << endl; Instruct_char(T);
default:cout << "输错了,请重新输入...\n" << endl; break;
}
}
}
void Calculate_Tree(Btree T)
{
Clear();
int choice = 0;
cout << "请选择:\n1、求树宽\n2、求树高\n3、返回次级页面\n4、返回主菜单\n";
while (cin >> choice && choice != 0)
{
cout << "请继续输入选项" << endl;
switch (choice)
{
case 1:cout << "递归求树宽:" << endl; cout << Tree_Width_recursion(T) << endl; cout << "层次遍历求树宽:" << endl; cout << Tree_Width(T) << endl; break;
case 2:cout << "递归求树深:" << endl; cout << Tree_Depth_recursion(T) << endl; cout << "层次遍历求树深:" << endl; cout << Tree_Depth(T) << endl; break;
case 3:Instruct_char(T);
case 4:Index();
default:cout << "输错啦,请重新输入...\n" << endl; break;
}
}
}
void Traverse(Btree T)
{
Clear();
int choice = 0;
Clear();
printf("1、前序遍历\n2、中序遍历\n3、后序遍历\n4、广度优先遍历\n5、深度优先遍历\n6、返回次级页面\n7、返回主菜单\n");
while (cin >> choice && choice != 0)
{
cout << "请输入选项..." << endl;;
switch (choice)
{
case 1:cout << "前序递归遍历" << endl; PreOrder_recursion(T); cout << endl; cout << "前序非递归使用栈遍历" << endl; PreOrder(T); cout << endl; break;
case 2:cout << "中序递归遍历" << endl; InOrder_recursion(T); cout << endl; cout << "中序非递归使用栈遍历" << endl; InOrder(T); cout << endl; break;
case 3:cout << "后序递归遍历" << endl; PostOrder_recursion(T); cout << endl; cout << "后序非递归使用栈遍历" << endl; PostOrder(T); cout << endl;
cout << "访问标记法结果为:" << endl; postOrder_visit(T); break;
case 4:cout << "广度优先遍历结果为:" << endl; Breadth_First_Search(T); cout << endl; cout << "层序遍历结果为:" << endl; Sequence_traverse(T); cout << endl; break;
case 5:cout << "深度优先搜索结果为:" << endl; Depth_First_Search(T); break;
case 6:Instruct_char(T);
case 7:Index();
default:cout << "输错啦,请重新输入..." << endl;
break;
}
}
}
void Estimate(Btree T)
{
Clear();
int choice = 0;
cout << "1、是否为完全二叉树\n2、是否为满二叉树\n3、返回次级页面\n4、返回主菜单" << endl;
while (cin >> choice && choice != 0)
{
cout << "请输入" << endl;
switch (choice)
{
case 1:cout << "是否为完全二叉树" << " " << isComplete_Tree(T) << endl; break;
case 2:cout << "是否为满二叉树" << " " << isFullBinaryTree(T) << endl; break;
case 3:Instruct_char(T);
case 4:Index();
default:cout << "输错啦,请重新输入..." << endl;
break;
}
}
}
void Path(Btree T)
{
Clear();
int choice = 0;
char E_path[maxsize];
int len = 0;
int pos = 0;
char data = '0';
cout << "请选择:1、所有叶子结点到根结点的路径\n2、最长路径\n3、查询结点\n4、返回次级页面\n5、返回主菜单\n";
while (cin >> choice && choice != 0)
{
cout << "请输入..." << endl;
switch (choice)
{
case 1:cout << "递归求所有叶子结点到根结点的路径" << endl; Every_path_recursion(T, E_path, len); cout << endl;
cout << "非递归法" << endl; AllPath(T); break; cout << endl; cout << "从根结点开始到树叶的所有路径:" << endl;
cout << "根结点到所有树叶的路径:" << endl; All_path_root_leaf(T, pos); cout << endl; break;
case 2:cout << "其中一条最长路径:" << endl; One_Longest_Path(T); cout << endl;
cout << "第一条最长路径:" << endl; Find_First_Longest_Path(T); Print_First_Longest_Path(T); cout << endl; break;
case 3:cout << "输入您要查询的结点:" << endl; Inquire_node(T, data); cout << "查询结果" << Inquire_node(T, data) << endl;
case 4:Instruct_char(T);
case 5:Index();
default:cout << "输错啦,请重新输入" << endl; break;
}
}
}
void Calculate_Node(Btree T)
{
Clear();
int choice = 0;
int zero = 0, one = 0, two = 0;
cout << "请选择:\n1、零度、一度、二度结点数量\n2、所有叶子结点数量\n3、输出所有树叶\n4、返回次级页面\n5、返回主菜单\n";
while (cin >> choice && choice != 0)
{
switch (choice)
{
case 1:cout << "各种结点的数量" << endl; Sum_node(T, zero, one, two); cout << endl; break;
case 2:cout << "所有结点的数量:" << endl; getAllNode(T); cout << endl; break;
case 3:cout << "输出所有叶子结点:" << endl; PrintLeaves(T); cout << endl; break;
case 4:Instruct_char(T);
case 5:Index();
default:cout << "输错啦,请重新输入..." << endl; break;
}
}
}
void Swap_child(Btree T)
{
Clear();
int choice = 0;
Btree T1 = nullptr;
Btree T2 = nullptr;
swap(T1, T2);
Node_Swap(T);
cout << "请选择:1、查看交换后的前序遍历结果\n2、返回次级页面\n3、返回主菜单" << endl;
cin >> choice;
while (choice)
{
switch (choice)
{
case 1:PreOrder_recursion(T); break;
case 2:Instruct_char(T);
case 3:Index();
default:cout << "输错啦,请重新输入..." << endl; break;
}
}
}
/*-----------------------------------------*/
//前序遍历创建树char
void Build(Btree& T) {
char ch;
cin >> ch;
if (ch == '0') T = NULL;
else {
T = (Tnode*)malloc(sizeof(Tnode));
T->data = ch;
Build(T->lchild);
Build(T->rchild);
}
}
//前序遍历创建树,使用char数组
void CreateTree(Btree& T, char chars[], int& i) {
cin >> chars[i];
if (chars[i] == '0') {
T = NULL;
}
else {
T = new Tnode;
T->data = chars[i];
CreateTree(T->lchild, chars, ++i); //递归构建左子树
CreateTree(T->rchild, chars, ++i); //递归构建右子树
}
}
Bntree Create_Number_Tree()
{
Bntree T;
int data = 0;
cin >> data;
if (data == -1) T = NULL;
else
{
T = new node;
T->data = data;
T->lchild = Create_Number_Tree();
T->rchild = Create_Number_Tree();
}
return T;
}
void CreateBiTree(Bntree* T)
{
int data;
scanf_s("%d", &data);
if (data == 0)
*T = NULL;
else
{
*T = (Bntree)malloc(sizeof(node));
if (!*T)
exit(1);
(*T)->data = data; //生成根结点
CreateBiTree(&(*T)->lchild);//构造左子树
CreateBiTree(&(*T)->rchild);//构造右子树
}
}
/*---------------------------------------*/
//前序递归 遍历
void PreOrder_recursion(Btree T) {
if (T != NULL) {
cout << T->data << " ";
PreOrder_recursion(T->lchild);
PreOrder_recursion(T->rchild);
}
}
//前序遍历非递归版本
//由于整个左子树被访问完才能访问右子树,故需要借助栈来保存当前子树的根节点
void PreOrder(Btree T) {
stack<Tnode*> S;//开辟一个栈
Btree p = T;//迭代指针 开始指向root
while (p || !S.empty()) { //只要还有结点
if (p) { //如果当前结点不空
cout << p->data << " "; //则打印当前结点 因为是先序,遇到新结点就打印
S.push(p);//当前结点入栈
p = p->lchild;//访问其左子树,向左访问结点
}
else {
p = S.top();//如果当前结点是空的,就退回到上一个结点
S.pop();//退栈
p = p->rchild;//访问其右子树
}
}
}
/*----------------------------------------*/
//中序递归 遍历
void InOrder_recursion(Btree T) {
if (T != NULL) {
InOrder_recursion(T->lchild);
cout << T->data << " ";
InOrder_recursion(T->rchild);
}
}
//中序非递归遍历 左 中 右
//根节点必须在左结点访问之后再访问,而根节点又是先于左子节点被遍历到,故要设置一个栈来保存
void InOrder(Btree T) {
stack<Tnode*> S;//开辟一个栈
Btree p = T;//迭代器
while (p || !S.empty()) { //如果还有结点
if (p) {//如果当前结点不为空
S.push(p);// 不要急于访问根节点,先压栈。
p = p->lchild;//访问左子树
}
else {//如果当前节点是空的。则需要退回到上一个结点
p = S.top();
S.pop();//退到该子树的根节点立即访问
cout << p->data << " ";
p = p->rchild;//继续访问右子树
}
}
}
/*---------------------------------------------*/
//后序递归 遍历
void PostOrder_recursion(Btree T) {
if (T != NULL) {
PostOrder_recursion(T->lchild);
PostOrder_recursion(T->rchild);
cout << T->data << " ";
}
}
//后序遍历非递归 双栈法
//由于是左 右 中,因此入栈次序是中右左,
//先看根节点,再看右孩子,再看左孩子
void PostOrder(Btree T) {
stack<Tnode*> S; //遍历栈
stack<Tnode*> result; //结果栈
Btree p = T;//迭代器
while (p || !S.empty()) {
if (p) { //如果当前结点不为空
S.push(p);//结点入栈
result.push(p);//结点入结果栈
p = p->rchild;//看其右孩子结点
}
else { //如果当前结点为空 ,退到上一个结点
p = S.top();
S.pop();//退栈
p = p->lchild;//找其左孩子结点
}
}
//输出后序序列
while (!result.empty()) {
p = result.top();
result.pop();
cout << p->data << " ";
}
}
// 后序遍历 访问标记法
void postOrder_visit(Btree T) {
stack<Tnode*> S; //开辟一个栈
Tnode* p = T; //迭代器
Tnode* r = NULL; //保存最近访问过的结点
while (p || !S.empty()) {
if (p) { //如果当前结点不为空 则走到该子树的最左边
S.push(p);
p = p->lchild;
}
else { //若为空,退到上一个结点
p = S.top();
if (p->rchild && p->rchild != r) { //如果存在右子树并且右子树没有被访问过
p = p->rchild;//那么就转向右子树继续
S.push(p); // 保存子树根节点
p = p->lchild; //继续向左访问左子树
}
else {
p = S.top();
S.pop();//没有右子树那就可以访问根节点了
cout << p->data << " ";
r = p; //标记r为最近访问的结点
p = NULL; //当前结点置为空 ,因为这棵子树的根节点都访问完了说明这颗子树就全部访问完了,就等待退回上一个子树根节点
}
}
}
}
/*-------------------------------------*/
//层次遍历(广度遍历)求树宽度
//在层次遍历基础上。增加对每一层结点数的统计,维护max
int Tree_Width(Btree T) {
int level = 0;
if (!T) return 0;
queue<Tnode*> Q;
Tnode* last = T; //记录每层最后一个结点,第一层最后一个节点就是根节点
Tnode* front = nullptr, * rear = nullptr;//记录队首结点 队尾结点
int ans = 0;//记录最大宽度
int cur = 0;//记录当前层的宽度
Q.push(T);//根节点入队
while (!Q.empty()) {
front = Q.front();//取队首
Q.pop();//队首弹出
cur++;
if (front->lchild) {
Q.push(front->lchild);//如果有左孩子那么左孩子入队
rear = front->lchild;
}
if (front->rchild) {
Q.push(front->rchild);//如果有右孩子那么右孩子入队
rear = front->rchild;
}
if (front == last) {//如果当前结点是该层最后一个结点
//cout<<front->data<<" ?? "<<rear->data<<endl;
level++;//那么层数+1 ,到达下一层
last = rear;//更新last,下一层的最后一个结点必然是最后入队的那个结点
//到达每层最后一个结点时就知道了这一层的总的结点数
//维护最大值即可
ans = max(ans, cur);
cur = 0;
}
}
return ans;
}
//递归遍历求树的宽度
//相当于先序遍历一遍然后把每个结点所在的层数记录下来
//每访问一个新结点就把该层的count加上1,最终得到所有层的宽度
void Tree_Width_recursion(Btree T, int level, int count[]) {
if (T == NULL) return; //如果子树树根为空就不要再统计下去
count[level]++;//树在第level层的宽度+1
Tree_Width_recursion(T->lchild, level + 1, count);
Tree_Width_recursion(T->rchild, level + 1, count);
}
int Tree_Width_recursion(Btree T) {
int count[200] = { 0 };
int maxx = 0;
Tree_Width_recursion(T, 0, count);
for (int i = 0; i < 200; i++) {
maxx = max(maxx, count[i]);
}
return maxx;
}
/*--------------------------*/
//递归求树高
int Tree_Depth_recursion(Btree T) {
if (T == NULL) return 0;
int rightTree = Tree_Depth_recursion(T->rchild);
int leftTree = Tree_Depth_recursion(T->lchild);
return (rightTree > leftTree) ? (rightTree + 1) : (leftTree + 1);
}
int Depth(Btree T)/* 再来一个求树深度的算法 */
{
if (T == NULL)
return 0;
return 1 + (Depth(T->lchild) > Depth(T->rchild) ? Depth(T->lchild) : Depth(T->rchild));
//选择左右孩子深度高的然后加上根节点这一层就是深度了
}
//层序(广度遍历)遍历求树高
int Tree_Depth(Btree T) {
int level = 0;
if (!T) return 0;
queue<Tnode*> Q;
Tnode* last = T; //记录每层最后一个结点,第一层最后一个节点就是根节点
Tnode* front = nullptr, * rear = nullptr;//记录队首结点 队尾结点
Q.push(T);//根节点入队
while (!Q.empty()) {
front = Q.front();//取队首
Q.pop();//队首弹出
if (front->lchild) {
Q.push(front->lchild);//如果有左孩子那么左孩子入队
rear = front->lchild;
}
if (front->rchild) {
Q.push(front->rchild);//如果有右孩子那么右孩子入队
rear = front->rchild;
}
if (front == last) {//如果当前结点是该层最后一个结点
//cout<<front->data<<" ?? "<<rear->data<<endl;
level++;//那么层数+1 ,到达下一层
last = rear;//更新last,下一层的最后一个结点必然是最后入队的那个结点
}
}
return level;
}
/*******************************************************************************************************/
//深度优先遍历
void Depth_First_Search(Btree root) {
stack<Tnode*> nodeStack; //使用C++的STL标准模板库
nodeStack.push(root);
Tnode* node;
while (!nodeStack.empty()) {
node = nodeStack.top();
cout << node->data;//遍历根结点
nodeStack.pop();
if (node->rchild) {
nodeStack.push(node->rchild); //先将右子树压栈
}
if (node->lchild) {
nodeStack.push(node->lchild); //再将左子树压栈
}
}
}
//广度优先遍历
void Breadth_First_Search(Btree root) {
queue<Tnode*> nodeQueue; //使用C++的STL标准模板库
nodeQueue.push(root);
Tnode* node;
while (!nodeQueue.empty()) {
node = nodeQueue.front();
nodeQueue.pop();
cout << node->data;//遍历根结点
if (node->lchild) {
nodeQueue.push(node->lchild); //先将左子树入队
}
if (node->rchild) {
nodeQueue.push(node->rchild); //再将右子树入队
}
}
}
//层序遍历 队列
void Sequence_traverse(Btree T) {
queue<Tnode*> Q;
Tnode* p = T;
Q.push(T);
while (!Q.empty()) {
p = Q.front();
Q.pop();
cout << p->data << " ";
if (p->lchild) Q.push(p->lchild);
if (p->rchild) Q.push(p->rchild);
}
}
/***************************************************************************************************/
/*---------------------------------------*/
//判断时否是完全二叉树
//利用性质 完全二叉树与满二叉树在层次遍历上的联系和区别,前者是后者序列的一部分
bool isComplete_Tree(Btree T) {
queue<Tnode*> Q;//Q中存储层次遍历序列
Tnode* p;
if (!T) return true;//空树也当成完全二叉树 它是满二叉树
Q.push(T);//首结点入队
while (!Q.empty()) { //如果Q不空
p = Q.front(); // 取出队首
Q.pop();
if (p) { //如果当前结点不空,将其左右孩子入队,不管孩子空不空
Q.push(p->lchild);
Q.push(p->rchild);
}
else { //如果当前结点为空,那么之后的序列不能有不空的结点,因为层次遍历ABCD.E显然是非法的
while (!Q.empty()) {
p = Q.front();
Q.pop();
if (p) return false;
}
}
}
return true;
}
bool isFullBinaryTree(Btree T) {
if (T == NULL) return true;
typedef std::pair<Btree, int> PTI; //pair的第二个模版参数用于记录层数
queue<PTI> q;
q.push(PTI(T, 1));
PTI curnode;
int prevdeepth = 0;
//用flag标识第一次出现叶子结点,其后的所有结点应该是叶子结点
int flag = false;
while (!q.empty()) {
curnode = q.front();
q.pop();
if ((curnode.first->lchild == NULL && curnode.first->rchild != NULL) //只有右孩子
||
curnode.first->lchild != NULL && curnode.first->rchild == NULL) //只有左孩子
return false;
if (flag) {
if (curnode.first->lchild == NULL && curnode.first->rchild == NULL)
;
else
return false; //叶子结点后续结点有非叶子结点
}
else {
if (curnode.first->lchild == NULL && curnode.first->rchild == NULL) {
if (curnode.second > prevdeepth) { //每一层的第一个结点一定大于前一结点的层数
flag = true;
}
else { //如果层数不大于前一结点层数,那一定是同一层
return false;
}
}
else {
q.push(PTI(curnode.first->lchild, curnode.second + 1));
q.push(PTI(curnode.first->rchild, curnode.second + 1));
}
}
prevdeepth = curnode.second;
}
return true;
}
//查询
/*-----------------*/
/*查找元素X所在的结点*/
Btree Inquire_node(Btree T, char x)
{
if (!T) return NULL;
if (x == T->data) return T;
return Inquire_node(T->lchild, x) != NULL ? Inquire_node(T->lchild, x) : Inquire_node(T->rchild, x);
}
/*----------------------*/
//递归求解所有叶子结点到根结点的路径
void Every_path_recursion(Btree T, char E_path[], int len)
{
if (T)
{
if (T->rchild == NULL && T->rchild == NULL)
{
cout << T->data;
for (int i = len - 1; i >= 0; i--)
cout << E_path[i];
cout << endl;
}
else
{
E_path[len] = T->data;
len++;
Every_path_recursion(T->lchild, E_path, len);
Every_path_recursion(T->rchild, E_path, len);
len--;
}
}
}
//非递归求所有路径(树叶到根结点)
void AllPath(Btree T)
{
struct node
{
int parent;
Btree node;
}qu[100];
Btree q;
int front, rear, p;
front = rear = -1;
rear++;
qu[rear].node = T;
qu[rear].parent = -1;
while (front != rear)
{
front++;
q = qu[front].node;
if (q->lchild == NULL && q->rchild == NULL)
{
p = front;
while (qu[p].parent != -1)
{
cout << qu[p].node->data << "->";
p = qu[p].parent;
}
cout << qu[p].node->data << endl;
}
if (q->lchild != NULL)
{
rear++;
qu[rear].node = q->lchild;
qu[rear].parent = front;
}
if (q->rchild != NULL)
{
rear++;
qu[rear].node = q->rchild;
qu[rear].parent = front;
}
}
}
//递归求解所有树根到树叶的路径
//存储所有的路径
//递归实现输出从根节点到叶子结束的所有路径
vector<char> path1(10, '0');
void All_path_root_leaf(Btree T, int pos)
{
if (T == NULL)
return;
path1[pos] = T->data;
if (T->rchild == NULL && T->lchild == NULL)
{
auto it = path1.begin();
auto end = find(path1.begin(), path1.end(), '0');
while (it != end)
{
cout << *it++ << " ";
}
cout << endl;
}
else
{
if (T->data != NULL)
{
All_path_root_leaf(T->lchild, pos + 1);
}
if (T->rchild != NULL)
{
All_path_root_leaf(T->rchild, pos + 1);
}
}
path1[pos] = '0';
}
vector<char> path;
void Find_First_Longest_Path(Btree T)
{
path.push_back(T->data);
if (T->lchild == NULL && T->rchild == NULL)
return;
else if (Depth(T->lchild) >= Depth(T->rchild))
Find_First_Longest_Path(T->lchild);
else
Find_First_Longest_Path(T->rchild);
}
void Print_First_Longest_Path(Btree T)
{
vector<char>::iterator it;
for (it = path.begin(); it != path.end(); it++)
cout << *it << " ";
path.clear();
}
void One_Longest_Path(Btree T)//其中一条
{
if (T != NULL)//在T不为空的情况下
{
if (Depth(T->lchild) > Depth(T->rchild))//判断往左走还是往右走
{
One_Longest_Path(T->lchild);
cout << T->data;
}
else
{
One_Longest_Path(T->rchild);
cout << T->data;
}
}
}
/*-----------------*/
//求解树的所有叶子
void PrintLeaves(Btree T)
{
if (T)
{
if (!T->rchild && !T->lchild) //如果BT节点是叶子
cout << T->data << " ";
PrintLeaves(T->rchild);
PrintLeaves(T->lchild);
}
}
/*-----------------*/
//统计二叉树的各个结点数量
void Sum_node(Btree T, int& zero, int& one, int& two)
{
if (T)
{
if (T->rchild != NULL && T->lchild != NULL) two++;
else if (T->rchild == NULL && T->lchild == NULL) zero++;
else one++;
Sum_node(T->rchild, zero, one, two);
Sum_node(T->lchild, zero, one, two);
}
}
//求解二叉树的所有结点个数
int getAllNode(Btree T)
{
if (NULL == T)
return 0;
return 1 + getAllNode(T->lchild) + getAllNode(T->rchild);
}
/*--------------*/
//交换树的左右孩子
void swap(Btree& T1, Btree& T2)
{
Btree t;
t = T1;
T1 = T2;
T2 = t;
}
void Node_Swap(Btree& T)
{
if (T)
{
if (T->rchild != NULL && T->lchild != NULL)
{
swap(T->rchild, T->lchild);
}
else if (T->lchild != NULL && T->rchild == NULL)
{
T->rchild = T->lchild;
T->lchild = NULL;
}
else if (T->lchild == NULL && T->rchild != NULL)
{
T->lchild = T->rchild;
T->rchild = NULL;
}
else
{
;//空操作
}
Node_Swap(T->lchild);
Node_Swap(T->rchild);
}
else
{
;//空操作
}
}
void inOrder(Bntree T)
{
if (T != NULL)
{
if ((T->data == '*' || T->data == '/') && (T->lchild->data == '+' || T->lchild->data == '-') && (T->rchild->data == '-' || T->rchild->data == '+'))//左右两边都需要加括号
{
cout << "(";
inOrder(T->lchild);
cout << ")";
cout << T->data;
cout << "(";
inOrder(T->rchild);
cout << ")";
}
else if ((T->data == '*' || T->data == '/') && (T->lchild->data == '+' || T->lchild->data == '-' || T->rchild->data == '-' || T->rchild->data == '+'))
{
inOrder(T->lchild);
cout << T->data;
cout << "(";
inOrder(T->rchild);
cout << ")";
}
else
{
inOrder(T->lchild);
cout << T->data;
inOrder(T->rchild);
}
}
}
/*-----------------------------------------树的中缀表达式求值---------------------------------------------*/
typedef struct StackNode
{
Btree data_tree; //存储的是二叉树
char data_op; //存储的是符号
StackNode* next;
}*LinkStack;
//栈的初始化
int InitStack(LinkStack& S)
{
S = NULL;
return 1;
}
//二叉树入栈
int Push_tree(LinkStack& S, Btree e)
{
LinkStack p = new StackNode;
p->data_tree = e;
p->next = S;
S = p;
return 1;
}
//字符(运算符号)入栈
int Push_op(LinkStack& S, char e)
{
LinkStack p = new StackNode;
p->data_op = e;
p->next = S;
S = p;
return 1;
}
//二叉树出栈
int Pop_tree(LinkStack& S, Btree& T1)
{
if (S == NULL) return 0;
LinkStack p = S;
T1 = p->data_tree;
S = S->next;
delete p;
return 1;
}
//字符(运算符号)出栈
int Pop_op(LinkStack& S, char& ch)
{
if (S == NULL) return 0;
LinkStack p = S;
ch = p->data_op;
S = S->next;
delete p;
return 1;
}
//取栈顶元素
char GetTop_op(LinkStack S)
{
if (S != NULL) return S->data_op;
else return ' ';
}
Btree GetTop_tree(LinkStack S)
{
if (S != NULL) return S->data_tree;
else return NULL;
}
/*------------------------------表达式树的创建算法------------------------------*/
//创建以T为根结点的二叉树(存储符号)
void CreateExpTree(Btree& T, Btree a, Btree b, char theta)//a是左孩子,b是右孩子,theta是数据域
{
Btree L = new Tnode;
L->data = theta;
L->lchild = a;
L->rchild = b;
T = L;
}
//创建以T为根结点的二叉树(存储数值,可大于9)
//a是左孩子,b是右孩子,theta是数据域
void CreateExpTree_str(Btree& T, Btree a, Btree b, string theta)
{
Btree L = new Tnode;
L->combine_data = theta;
L->lchild = a;
L->rchild = b;
T = L;
}
//比较运算符的优先级
//top是栈顶元素,ch是需要比较的元素
char Precede(char top, char ch)
{
if (ch == ')' && top == '(') return '=';
else if (ch == ')') return '>';
if (top == ' ' || top == '(' || ch == '(') return '<';
if (ch == '=') return '>';
if (top == '+' || top == '-') {
if (ch == '+' || ch == '-') return '>';
else if (ch == '/' || ch == '*') return '<';
}
else if (top == '*' || top == '/') return '>';
}
//创建表达式树
//expt栈(根结点),optr栈(运算符)
void InitExpTree(char ep[], LinkStack& expt, LinkStack& optr)
{
int n = strlen(ep);
int i = 0;
Btree T = NULL; //树根
Btree T1 = NULL; //左子树
Btree T2 = NULL; //右子树
char ch = ' '; //弹出的符号
string combine_str = ""; //存储数值,可大于9
while (i != n)
{
if (ep[i] >= '0' && ep[i] <= '9') { //数值(二叉树),进入expt栈中
combine_str += ep[i];
if (ep[i + 1] >= '0' && ep[i + 1] <= '9') { //下一位仍是数字,需连接
i++;
continue;
}
CreateExpTree_str(T, NULL, NULL, combine_str);
combine_str = ""; //建完数值的二叉树后string要置空
Push_tree(expt, T);
i++;
}
else {
switch (Precede(GetTop_op(optr), ep[i])) //比较优先级
{
case '<':
Push_op(optr, ep[i]);
i++;
break;
case '>':
Pop_op(optr, ch); //弹出上一个字符
Pop_tree(expt, T1); //弹出上两个数值(二叉树)
Pop_tree(expt, T2);
CreateExpTree(T, T2, T1, ch); //以data_tree为根,连接T1和T2两颗子树
Push_tree(expt, T); //最后把T放进expt栈中
break;
case '=':
Pop_op(optr, ch);
i++;
break;
default:
break;
}
}
}
}
//表达式树的后序遍历
void PostOrder_get(Btree T)
{
if (T)
{
PostOrder_get(T->lchild);
PostOrder_get(T->rchild);
if (T->lchild == NULL && T->rchild == NULL) {
cout << T->combine_data << " ";
}
else cout << T->data << " ";
}
}
/*-----------------------------表达式树的求值-------------------------------*/
//根据当前结点运算符的例子那个进行相应运算
double GetValue(char data, double lvalue, double rvalue)
{
switch (data)
{
case '+':
return lvalue + rvalue;
break;
case '-':
return lvalue - rvalue;
break;
case '*':
return lvalue * rvalue;
break;
case '/':
return lvalue / rvalue;
break;
default:
break;
}
}
//把string字符转换成数值
double change(string str)
{
int n = str.length(), m = str.length();
double sum = 0;
for (int i = 0; i < n; i++)
{
sum += (str[i] - '0') * pow(10, m - 1);
m--;
}
return sum;
}
//遍历表达式树求表达式的值
double EvaluateExpTree(Btree T)
{
double lvalue = 0, rvalue = 0; //存放叶子结点的数据域初始为0
if (T->lchild == NULL && T->rchild == NULL)
return change(T->combine_data); //return T->data - '0';
else {
lvalue = EvaluateExpTree(T->lchild); //相当于后序遍历二叉树
rvalue = EvaluateExpTree(T->rchild);
return GetValue(T->data, lvalue, rvalue);
}
}
void Func()
{
Clear();
//char ep[] = "3+4*(6-1)-8/2#"; //"(18-2)*(13-7)+4/2#";
char s[maxsize];
int i = 0;
cout << "请输入表达式 ..." << endl;
while (cin >> s && s != "=")
{
if (s[0] == '0')
Index();
LinkStack expt;
InitStack(expt); //初始化expt栈(根结点)
LinkStack optr;
InitStack(optr); //初始化optr栈(运算符)
InitExpTree(s, expt, optr); //构建表达式树
Btree T = NULL;
Pop_tree(expt, T); //获取最后建好的二叉树
cout << "初始的中缀表达式: " << s << endl; //初始中缀表达式
cout << "后序遍历: ";
PostOrder_get(T); //后序遍历结果
cout << endl;
cout << "表达式求值后的结果: " << EvaluateExpTree(T) << endl; //表达式树求值结果
i++;
if (i > 0)
cout << "请继续输入表达式求值或输入 0 返回主菜单..." << endl;
}
}