以前采用先序遍历的方式创建二叉树,每次测试的时候都需要重新输入树的结点。
命令行输入树
/**
* 先序建立二叉树 TLR
* @param T 引用 main 函数中定义的树根节点的地址
*/
void createBintree(Bintree &T) {
char data;
cin >> data;
getchar(); // 接收 space 或 enter
if (data == '#') { // # 结束符
T = nullptr;
} else {
T = (Bintree) malloc(sizeof(Bnode)); // 新建节点
T->data = data;
cout << data << " 左节点(#结束): ";
createBintree(T->Lchild);
cout << data << " 右节点(#结束): ";
createBintree(T->Rchild);
}
}
比如创建上图这棵树,运行时,需要输入:
输入树的根结点: 1
1 左结点(#结束): 2
2 左结点(#结束): #
2 右结点(#结束): #
1 右结点(#结束): 3
3 左结点(#结束): 4
4 左结点(#结束): #
4 右结点(#结束): #
3 右结点(#结束): 5
5 左结点(#结束): #
5 右结点(#结束): #
每次都这样,一开始有这么多输入,就很影响效率,之后我在先序创建树的基础上,将 cin >> data
替换为 readTree >> data
从文件中读取结点,就不用每次输入了。
文件读取树
ifstream readTree; // 定义全局的输入文件流
/**
* 仿照 createBintree 递归读取文件结点 先序创建树
*/
void readData(Bintree &T) {
char data;
readTree >> data;
if (data == '#') { // # 结束符
T = nullptr;
} else {
T = (Bintree) malloc(sizeof(Bnode)); // 新建节点
T->data = data;
readData(T->Lchild);
readData(T->Rchild);
}
}
/**
* 从文件读取树的结点
* @param filename 文件名
* @param T 树根
*/
void createTreeFromFile(const string &filename, Bintree &T) {
readTree.open(filename); // 打开文件流
if (!readTree.is_open()) {
cout << "Open Error";
exit(0);
}
readData(T); // 读取文件建树
readTree.close(); // 关闭文件流
}
测试
tree.txt
1 2 # # 3 4 # # 5 # #
int main() {
// 从文件读取创建树
Bintree bintree;
createTreeFromFile("../tree.txt", bintree); // 相对路径
// 三序遍历和层序
cout << "先序遍历: ";
preOrder(bintree);
cout << endl;
cout << "中序遍历: ";
inOrder(bintree);
cout << endl;
cout << "后序遍历: ";
postOrder(bintree);
cout << endl;
cout << "层序遍历: ";
levelOrder(bintree);
cout << endl;
// 树高
cout << "树的高度: " << depthBintree(bintree) << endl << endl;
return 0;
}
先序遍历: 1 2 3 4 5
中序遍历: 2 1 4 3 5
后序遍历: 2 4 5 3 1
层序遍历: 1 2 3 4 5
树的高度: 3
遍历用到的函数:二叉树三序遍历 + 层序遍历(循环队列)