一. 数的括号表示法
1、树的线性表示
树型结构和线性结构的主要区别在于树型结构具有分支性和层次性。使用树的遍历操作,可以将树中的结点按照规定的顺序排成一个线性序列;然而仅凭借树的某种遍历序列有时无法唯一地确定一棵树,但只要在遍历序列的基础上增加一些附加信息便可以唯一地确定一棵树,从而得到树的线性表示。树的线性表示便于树的输入、输出,同时在存储时也比较节省空间。
2、树的括号表示规则
(1)若树T为空树,则其括号表示为空
(2)若树T只包含一个结点,则其括号表示即为该结点本身
(3)若树T由根结点A和它的m棵子树T1,T2,...,Tm构成,则其括号表示为:A(T1的括号表示,T2的括号表示,... ,Tm的括号表示)
其中,子树的括号表示同样应该遵循以上规则
上图中树的括号表示为 A(B,C(F,G,H),D,E(I,J))
实现方法如下:
(1)从左到右扫描树的括号表示;
(2)每当遇到左括号时,其前一个结点进栈,并读入下一个符号;
(3)每当遇到右括号时,栈顶元素出栈。说明以栈顶元素为根的树(子树)构造完毕,此时若栈为空,算法结束,否则读入下一个符号
(4)每当遇到结点时,则它一定为栈顶元素的子女,将其挂到栈顶元素的某子女位置上,并读入下一个符号;
(5)每当遇到“,”,则略过该符号,并读入下一个符号。
通过一个例子说明具体实现代码如下:
设一棵完全二叉树为1(2(4(8,9),5(10,11)),3(6(,12),7)) ,图形表示为
二、括号表达式序列化为树形结构
TreeNode* prase(string& data)
{
TreeNode* root = nullptr;
char ch = data[0];
bool isLeft = false;
TreeNode* lastNode = nullptr;
stack<TreeNode*> nodeStack;
int curIn = 0;
while (ch != '\0')
{
switch(ch) {
case '(' :
isLeft = true;
nodeStack.push(lastNode);
break;
case ',' :
isLeft = false;
break;
case ')' :
isLeft = false;
nodeStack.pop();
break;
default:
lastNode = new TreeNode(ch - '0');
if (root == nullptr)
{
root = lastNode;
} else {
TreeNode* parentNode = nodeStack.top();
if (isLeft)
{
parentNode->left = lastNode;
} else {
parentNode->right = lastNode;
}
}
break;
}
curIn++;
if (curIn == data.length())
{
break;
}
ch = data[curIn];
}
return root;
}
三、 树形结构转为括号表达式
void normalizeTree(TreeNode* root, string& str)
{
if (root == nullptr)
{
return;
}
str += to_string(long long(root->val));
if (root->left != nullptr || root->right != nullptr)
{
str += "(";
normalizeTree(root->left, str);
str += ",";
normalizeTree(root->right, str);
str += ")";
}
}
四、先序遍历输出二叉树
void preOrder(TreeNode* root)
{
if (root == nullptr)
{
return;
}
cout << root->val;
preOrder(root->left);
preOrder(root->right);
}
五、完整程序
#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <algorithm>
#include <iostream>
#include <set>
#include <algorithm>
#include <sstream>
#include <queue>
#include <iomanip>
#include <stack>
using namespace std;
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int v) : val(v), left(nullptr), right(nullptr)
{
}
};
void preOrder(TreeNode* root)
{
if (root == nullptr)
{
return;
}
cout << root->val;
preOrder(root->left);
preOrder(root->right);
}
TreeNode* prase(string& data)
{
TreeNode* root = nullptr;
char ch = data[0];
bool isLeft = false;
TreeNode* lastNode = nullptr;
stack<TreeNode*> nodeStack;
int curIn = 0;
while (ch != '\0')
{
switch(ch) {
case '(' :
isLeft = true;
nodeStack.push(lastNode);
break;
case ',' :
isLeft = false;
break;
case ')' :
isLeft = false;
nodeStack.pop();
break;
default:
lastNode = new TreeNode(ch - '0');
if (root == nullptr)
{
root = lastNode;
} else {
TreeNode* parentNode = nodeStack.top();
if (isLeft)
{
parentNode->left = lastNode;
} else {
parentNode->right = lastNode;
}
}
break;
}
curIn++;
if (curIn == data.length())
{
break;
}
ch = data[curIn];
}
return root;
}
void normalizeTree(TreeNode* root, string& str)
{
if (root == nullptr)
{
return;
}
str += to_string(long long(root->val));
if (root->left != nullptr || root->right != nullptr)
{
str += "(";
normalizeTree(root->left, str);
str += ",";
normalizeTree(root->right, str);
str += ")";
}
}
int main()
{
string data = "1(2(,5),3)";
TreeNode* rootNode = prase(data);
string str = "";
normalizeTree(rootNode, str);
preOrder(rootNode);
return 0;
}
参考:
[1] https://blog.csdn.net/baiziyuandyufei/article/details/43021011