使用先序遍历构建二叉树并进行遍历的完整指南
在数据结构中,二叉树是一个非常重要的概念。理解如何构建二叉树和遍历二叉树是学习数据结构的基础。在这篇博客中,我们将使用C++代码展示如何通过先序遍历的方法来构建二叉树,并展示几种常见的遍历方法:先序遍历、中序遍历和后序遍历,包括递归和非递归实现。
目录
1. 初始化二叉树
2. 使用先序遍历创建二叉树
3. 判断二叉树是否为空
4. 遍历二叉树的各种方法
- 递归先序遍历
- 非递归先序遍历
- 递归中序遍历
- 非递归中序遍历
- 递归后序遍历
- 非递归后序遍历
5. 释放二叉树
6. 示例测试
1. 初始化二叉树
我们首先需要初始化一个空的二叉树。这一步非常重要,因为在C++中,未初始化的指针会指向未知的内存地址,这会导致未定义行为。我们通过将指针设置为 `nullptr` 来初始化二叉树。
void initBTree(BTree& T) {
T = nullptr;
cout << "初始化成功!" << endl;
}
2. 使用先序遍历创建二叉树
先序遍历是构建二叉树的一种有效方法。我们从根节点开始,依次创建左子树和右子树。用户输入 `#` 表示该节点为空。
BTree createBTree(BTree& T) {
char ch;
cin >> ch;
cin.ignore();
if (ch == '#') {
return nullptr;
}
T = (BTree)malloc(sizeof(struct BTreeNode));
if (!T) {
cout << "开辟空间失败" << endl;
}
T->data = ch;
cout << "请输入左儿子" << endl;
T->lchild = createBTree(T->lchild);
cout << "请输入右儿子" << endl;
T->rchild = createBTree(T->rchild);
return T;
}
3. 判断二叉树是否为空
我们需要一个函数来判断二叉树是否为空。这可以通过检查根节点指针是否为 `nullptr` 来实现。
bool BTreeNULL(BTree& T) {
return T == nullptr;
}
4. 遍历二叉树的各种方法
递归先序遍历
先序遍历按顺序访问根节点、左子树和右子树。递归实现非常直观。
void preOrderTraversal_1(BTree& T) {
if (T == nullptr) {
return;
}
else {
cout << T->data << " ";
preOrderTraversal_1(T->lchild);
preOrderTraversal_1(T->rchild);
}
}
非递归栈实现先序遍历
使用栈来模拟递归的过程,逐步访问每一个节点。
void preOderTraversal_0(BTree& T) {
stack<BTree> S;
BTree p = T;
while (p || !S.empty()) {
if (p) {
cout << p->data << " ";
S.push(p);
p = p->lchild;
}
else {
p = S.top()->rchild;
S.pop();
}
}
cout << endl;
}
递归中序遍历
中序遍历按顺序访问左子树、根节点和右子树。
void inOrderTraversal_1(BTree& T) {
if (T == nullptr) {
return;
}
else {
inOrderTraversal_1(T->lchild);
cout << T->data << " ";
inOrderTraversal_1(T->rchild);
}
}
非递归栈实现中序遍历
使用栈来模拟递归的过程,逐步访问每一个节点。
void inOrderTraversal_0(BTree& T) {
stack<BTree> S;
BTree p = T;
while (p || !S.empty()) {
if (p) {
S.push(p);
p = p->lchild;
}
else {
cout << S.top()->data << " ";
p = S.top()->rchild;
S.pop();
}
}
cout << endl;
}
递归后序遍历
后序遍历按顺序访问左子树、右子树和根节点。
void postOrderTraversal_1(BTree& T) {
if (T == nullptr) {
return;
}
else {
postOrderTraversal_1(T->lchild);
postOrderTraversal_1(T->rchild);
cout << T->data << " ";
}
}
非递归栈实现后序遍历
使用栈来模拟递归的过程,记录最后访问的节点以决定何时访问右子树。
void postOrderTraversal_0(BTree& T) {
stack<BTree> S;
BTree p = T;
BTree lastVisited = nullptr;
while (p || !S.empty()) {
while (p) {
S.push(p);
p = p->lchild;
}
BTree topNode = S.top();
if (topNode->rchild && lastVisited != topNode->rchild) {
p = topNode->rchild;
}
else {
cout << topNode->data << " ";
lastVisited = topNode;
S.pop();
}
}
cout << endl;
}
5. 释放二叉树
为了防止内存泄漏,我们需要在使用完二叉树后释放所有分配的内存。
void freeBTree(BTree& T) {
if (T != nullptr) {
freeBTree(T->lchild);
freeBTree(T->rchild);
free(T);
}
}
6. 示例测试
以下是一个完整的测试示例,展示了如何构建和遍历二叉树。
int main() {
BTree T;
initBTree(T);
T = createBTree(T);
if (BTreeNULL(T)) cout << "二叉树为空" << endl;
else {
cout << "递归先序遍历" << endl;
preOrderTraversal_1(T);
cout << endl;
cout << "非递归先序遍历" << endl;
preOderTraversal_0(T);
cout << "递归中序遍历" << endl;
inOrderTraversal_1(T);
cout << endl;
cout << "非递归实现中序遍历" << endl;
inOrderTraversal_0(T);
cout << "递归实现后序遍历" << endl;
postOrderTraversal_1(T);
cout << endl;
cout << "非递归实现后序遍历" << endl;
postOrderTraversal_0(T);
}
freeBTree(T); // 释放二叉树
return 0;
}
总结
本文介绍了如何使用先序遍历构建二叉树,并展示了递归和非递归方法实现的先序、中序和后序遍历。通过这些示例代码,你可以更好地理解二叉树的结构和遍历方法。