C++数据结构之二叉搜索树的实现详解

C++数据结构之二叉搜索树的实现详解

1. 什么是二叉搜索树?

二叉搜索树是一种二叉树,其中每个节点都包含一个键值,且每个节点的键值都大于其左子树中任何节点的键值,小于其右子树中任何节点的键值。如下图所示:

        9
       / \
      4   15
         /  \
       12    20

在上面的二叉搜索树中,节点的键值分别是9, 4, 15, 12, 20,且每个节点的键值都符合上述定义。

2. 为什么需要二叉搜索树?

二叉搜索树可以支持快速的“查找”、“插入”和“删除”操作。这些操作均具有较低的时间复杂度,因此,二叉搜索树经常被用于需要高效查找、插入和删除操作的场合。

3. 二叉搜索树的实现

3.1 节点的定义

从二叉搜索树的定义可以看出,每个节点包含一个键值,因此,我们需要一个节点的结构体。对于每个节点,我们需要记录其键值,以及其左右子节点的指针。

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

3.2 实现“插入”操作

插入操作是将一个新节点插入到二叉搜索树中。要插入新节点,我们需要遍历二叉搜索树,找到一个合适的位置,使得新节点的键值满足二叉搜索树的定义。

class BST {
public:
    TreeNode* insert(int val) {
        if (root_ == nullptr) {
            root_ = new TreeNode(val);
            return root_;
        }
        TreeNode* p = root_;
        while (true) {
            if (val < p->val) {
                if (p->left == nullptr) {
                    p->left = new TreeNode(val);
                    return p->left;
                }
                p = p->left;
            } else {
                if (p->right == nullptr) {
                    p->right = new TreeNode(val);
                    return p->right;
                }
                p = p->right;
            }
        }
    }

private:
    TreeNode* root_ = nullptr;
};

在这段代码中,我们使用指针变量p来遍历二叉搜索树,找到合适的插入位置。如果val小于p的键值,则将p的指针移动到其左子节点,否则将其指针移动到右子节点,直到找到需要插入节点的位置。如果根节点为空,则直接在根节点处插入新节点。

3.3 实现“查找”操作

查找操作可以在二叉搜索树中查找一个键值是否存在。这也需要遍历二叉搜索树,查找对应的节点。

class BST {
public:
    bool search(int val) {
        TreeNode* p = root_;
        while (p != nullptr) {
            if (p->val == val)
                return true;
            if (p->val > val)
                p = p->left;
            else
                p = p->right;
        }
        return false;
    }

private:
    TreeNode* root_ = nullptr;
};

在这段代码中,我们使用指针变量p来遍历二叉搜索树,找到对应的节点。如果当前节点的键值等于目标值,则返回true;否则,根据键值的大小关系,将p的指针移动到左右子节点。

3.4 实现“删除”操作

删除操作可以将二叉搜索树中的某个节点删除。删除节点有三种情况:对应节点没有子节点、对应节点只有一个子节点、对应节点有两个子节点。我们需要针对这三种情况来进行删除操作。

class BST {
public:
    void deleteNode(int val) {
        TreeNode* cur = root_;
        TreeNode* pre = nullptr;
        while (cur != nullptr && cur->val != val) {
            pre = cur;
            if (cur->val < val)
                cur = cur->right;
            else
                cur = cur->left;
        }
        if (cur == nullptr)
            return;
        if (cur->left != nullptr && cur->right != nullptr) {
            TreeNode* t = cur->right;
            while (t->left != nullptr)
                t = t->left;
            cur->val = t->val;
            cur = t;
            pre = cur->right;
        }
        TreeNode* c;
        if (cur->left != nullptr)
            c = cur->left;
        else
            c = cur->right;
        if (cur == root_)
            root_ = c;
        else if (pre->left == cur)
            pre->left = c;
        else
            pre->right = c;
        delete cur;
    }

private:
    TreeNode* root_ = nullptr;
};

在这段代码中,我们使用指针变量curpre来遍历二叉搜索树,找到对应的节点。如果当前节点有两个子节点,则用其右子树的最左节点来替换当前节点,并将删除操作转换为删除该最左节点的操作。如果当前节点只有一个子节点,则将其子节点指针赋值给当前节点的父节点。如果当前节点没有子节点,则直接将其删除。

4. 示例

4.1 示例一:从数组构建二叉搜索树

int main() {
    vector<int> nums = {9, 4, 15, 12, 20};
    BST bst;
    for (int num : nums)
        bst.insert(num);
    cout << bst.search(12) << endl; // 1
    cout << bst.search(19) << endl; // 0
    bst.deleteNode(15);
    cout << bst.search(15) << endl; // 0
    return 0;
}

在这个示例中,我们使用BST类来实现二叉搜索树的操作。首先将数组nums插入到二叉搜索树中,然后查找数值为12的节点是否存在,结果为1;查找数值为19的节点是否存在,结果为0。最后删除键值为15的节点,并再次查找,结果为0。

4.2 示例二:从文件构建二叉搜索树

int main() {
    ifstream infile;
    infile.open("data.txt");
    if (!infile) {
        cout << "Error: file not found" << endl;
        return 0;
    }
    BST bst;
    int num;
    while (infile >> num)
        bst.insert(num);
    infile.close();
    cout << bst.search(7) << endl; // 1
    return 0;
}

在这个示例中,我们从文件中读取数字,然后插入到二叉搜索树中。在本例中,数据存储在data.txt文件中。最后查找数值为7的节点是否存在,结果为1。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++数据结构之二叉搜索树的实现详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 「分治」黑白棋子的移动

    本题为3月23日23上半学期集训每日一题中A题的题解 题面 题目描述 有2n个棋子(n≥4)排成一行,开始位置为白子全部在左边,黑子全部在右边,如下图为n=5的情形: ○○○○○●●●●● 移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能…

    算法与数据结构 2023年4月18日
    00
  • 二叉搜索树的本质

    引言 打算写写树形数据结构:二叉查找树、红黑树、跳表和 B 树。这些数据结构都是为了解决同一个基本问题:如何快速地对一个大集合执行增删改查。 本篇是第一篇,讲讲搜索树的基础:二叉搜索树。 基本问题 如何在一千万个手机号中快速找到 13012345432 这个号(以及相关联信息,如号主姓名)? 最笨的方案 把一千万个手机号从头到尾遍历一遍,直到找到该手机号,返…

    算法与数据结构 2023年4月17日
    00
  • 数据结构 红黑树的详解

    数据结构:红黑树的详解攻略 一、红黑树的定义 红黑树是一种二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是红色或黑色。红黑树的特征是对于任何有效的红黑树,从根到叶子结点或空子结点的每条路径都包含相同数目的黑色结点。 二、插入操作 对于新插入的节点,将其涂红并插入红黑树中,然后按照二叉搜索树的规则将其插入到红黑树中。 如果父节点是黑色,则不需…

    数据结构 2023年5月17日
    00
  • redis中的数据结构和编码详解

    Redis中的数据结构和编码详解 Redis中的数据结构 Redis支持以下五种数据结构: 字符串(string):最基本的数据类型,Redis中的字符串是二进制安全的,意味着您可以在字符串中存储任何数据。例如,您可以将图像文件或序列化对象存储为Redis字符串。字符串最大可以容纳512MB。 列表(list):Redis列表是字符串列表,其中的元素按照插入…

    数据结构 2023年5月17日
    00
  • C++二叉树结构的建立与基本操作

    C++二叉树是一种非常常见的数据结构,同时也是算法中经常使用的一种数据结构。本文将详细讲解C++二叉树的建立和基本操作,包括二叉树的定义、创建、遍历和删除等。 1. 二叉树的定义 二叉树是一种树形结构,每个节点最多只有两个子节点:左子节点和右子节点。树的深度取决于有多少个节点,根节点是最顶端的节点,不再有父节点。节点之间存在一些有天然排序关系且有先后性的关系…

    数据结构 2023年5月17日
    00
  • C语言数据结构实现银行模拟

    C语言数据结构实现银行模拟攻略 背景介绍 银行模拟是计算机学科中一个重要的数据结构实践练习项目。它涉及到队列(Queue)等数据结构的应用,也是计算机基础课程的一个重要组成部分。 代码实现 1. 队列的实现 首先,我们需要实现一个队列(Queue)结构体,包含 QueueSize、Front、Rear 三个成员变量: struct Queue { int Q…

    数据结构 2023年5月17日
    00
  • Raft协议及伪码解析

    目录 节点的状态转换 follower candidate leader 伪码部分 节点初始化(Initialazation) 选举时其他节点的视角 回到candidate选举时的视角 消息如何广播复制 重要的反复出现的ReplicateLog 节点收到了LogRequest 节点如何追加log,Appendentries 再次回到leader, 如何处理L…

    算法与数据结构 2023年4月17日
    00
  • 深入浅析C语言中堆栈和队列

    深入浅析C语言中堆栈和队列 堆栈(Stack) 堆栈是一种先进后出(Last In First Out,LIFO)的线性数据结构,只允许在一端进行插入和删除操作。堆栈在C语言中常用于函数调用时的参数传递、表达式求值和程序中断处理等场景。 实现堆栈的基本操作 下面是堆栈的基本操作,可以用数组来实现: 初始化 #define MAX_SIZE 100 // 假设…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部