数据结构--树

使用先序遍历构建二叉树并进行遍历的完整指南

在数据结构中,二叉树是一个非常重要的概念。理解如何构建二叉树和遍历二叉树是学习数据结构的基础。在这篇博客中,我们将使用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;
}

总结

本文介绍了如何使用先序遍历构建二叉树,并展示了递归和非递归方法实现的先序、中序和后序遍历。通过这些示例代码,你可以更好地理解二叉树的结构和遍历方法。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值