二叉树的广义表示形式:
a:表示根节点为a,左右节点均为空
a(b):表示根节点为a,左节点为b,右节点为空
a(,c):表示根节点为a,左节点为空,右节点为c
a(b,c)表示父节点为a,左子节点与右子节点分别为b和c
同样的表示方法还有a(b(d),c)
存储广义表二叉树的方法:
将广义表创建成二叉树,可以借助栈来实现。
利用栈先进先出的特点,如果左孩子节点不为空,则将其作为栈顶节点(即父亲节点)的左孩子并压入栈中,递归左子树
如果右孩子不为空,则将其作为栈顶元素的右孩子并压入栈中,递归右子树
伪代码如下:
设置一个标记变量 k,初始为 -1;
设置一个标记节点 p;
循环遍历存储广义表的字符串 str:
如果 str[i] 是左括号:
则设置 k 为 0;
把 p 压入栈中。
否则如果 str[i] 是逗号:
则设置 k 为 1。
否则如果 str[i] 是右括号:
则栈顶元素出栈。
否则如果 str[i] 是一个字母,用节点 temp 来存储:
如果 k 为 -1:
则把 temp 作为根节点并压入栈中。
如果 k 为 0:
如果此时栈顶节点是 p,则先出栈;
然后将 temp 作为栈顶节点的左孩子;
再把 temp 压入栈中。
如果 k 为 1:
栈顶元素出栈;
将 temp 作为栈顶节点的右孩子;
再把 temp 压入栈中。
代码实现:
Node* build(const string& input) {
stack<Node*> treeStack;
int k = -1;
for (int i = 0; i < input.length(); ++i) {
if (input[i] == '(') {
k = 0;
treeStack.push(new Node(input[i]));
}
else if (input[i] == ',') {
k = 1;
}
else if (input[i] == ')') {
treeStack.pop();
}
else {
Node* temp = new Node(input[i]); //暂存
if (k == -1) {
treeStack.push(temp);
}
else if (k == 0) {
treeStack.pop(); //栈顶元素出栈
treeStack.top()->lchild = temp;
treeStack.push(temp);
}
else if (k == 1) {
treeStack.pop();
treeStack.top()->rchild = temp;
treeStack.push(temp);
}
}
}
return treeStack.top(); //最后返回的是根节点
}
存储广义表二叉树的方法:
输出二叉树的广义表形式,有点类似于二叉树的先序遍历
先输出根节点,如果左孩子不为空则递归输出左子树,如果右孩子不为空则递归输出右子树,在输出过程中,根据节点是否为空,在合适的地方输出左右括号及逗号
伪代码如下:
输出节点存储的值;
如果左孩子不为空:
输出 "(";
递归输出左子树;
如果右孩子为空:
输出 ")"。
如果右孩子不为空:
如果左孩子为空:
输出 "("。
输出 “,”;
递归输出右子树;
输出 ")"。
代码如下:
void print() {
cout << data;
if (lchild != nullptr) {
cout << "(";
lchild->print();
if (rchild == nullptr) {
cout << ")";
}
}
if (rchild != nullptr) {
if (lchild == nullptr) {
cout << "(";
}
cout << ",";
rchild->print();
cout << ")";
}
}