题目描述:
写一个算法,读入任意一棵树的符号表示,并构建其内部表示。即树的广义表形式转换为链表形式。
如由A(B(E(K,L),F),C(G),D(H(M),I,J))表示的树长这个样子:
参考博客点击这里
代码:
Tree.h
#pragma once // 防止头文件被多次包含
#include <iostream>
#include <stack>
/*
1.定义树结点类TreeNode。
2.定义树类,数据成员为一棵树的根,成员函数build为
根据一棵树的符号表示创建一棵树的链表表示。
3.使用递归型中序遍历验证结果。
*/
class Tree;
class TreeNode {
friend class Tree;
private:
char key;
TreeNode* LeftChild;
TreeNode* RightChild;
public:
TreeNode(char c) {
key = c;
LeftChild = NULL;
RightChild = NULL;
}
};
class Tree {
private:
TreeNode* root;
public:
void build(const std::string & str);
void Inorder();
void inorder(TreeNode* curr);
};
Tree.cpp, 实现树的广义表表示到链表表示的核心思想是利用栈先进后出的特点。
#include "Tree.h"
/*
广义表转二叉树:
设置一个标记变量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压入栈中。
*/
void Tree::build(const std::string & str) {
if (0 == str.size()) root = NULL;
int flag = -1;
TreeNode* p = new TreeNode('#');
TreeNode* tmp;
std::stack<TreeNode* > stk;
for (int i=0;i<str.size();i++) {
if ('(' == str[i]) {
flag = 0;
stk.push(p);
}else if (',' == str[i]) {
flag = 1;
}else if (')' == str[i]) {
stk.pop();
}else {
tmp = new TreeNode(str[i]);
if (-1 == flag) {
stk.push(tmp);
root = tmp;
}else if (0 == flag) {
stk.pop();
stk.top()->LeftChild = tmp;
stk.push(tmp);
}else {
stk.pop();
stk.top()->RightChild = tmp;
stk.push(tmp);
}
}
}
}
void Tree::Inorder() { // 中序遍历驱动器
if (!root) {
std::cout<<"empty tree"<<std::endl;
return;
}
inorder(root);
}
void Tree::inorder(TreeNode* curr) { // 中序遍历递归核心
if (curr) {
inorder(curr->LeftChild);
std::cout<<curr->key;
inorder(curr->RightChild);
}
}
Main.cpp: 进行测试
#include "Tree.h"
/*
1.将二叉树由广义表表示转换为链表连接
2.中序遍历构造出的二叉树,检查正确性
*/
int main() {
std::string str = "A(B(D(G,F),E),C(H,I))";
Tree t;
t.build(str);
t.Inorder();
std::cin.get();
return 0;
}
中序遍历输出结果:GDFBEAHCI