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日

相关文章

  • C语言数据结构与算法之图的遍历(一)

    我来给您详细讲解一下“C语言数据结构与算法之图的遍历(一)”的完整攻略。 简介 本篇攻略主要介绍了图的遍历问题。图是由若干个点和连接这些点的边构成的数据结构,常用来表示复杂的关系和网络。图的遍历就是从图的某一点开始,按照一定的规则沿着边逐个访问图中所有的点,不重不漏地遍历整个图。 在本篇攻略中,我们将探讨图的深度优先遍历(DFS)和广度优先遍历(BFS)两种…

    数据结构 2023年5月17日
    00
  • Java数据结构之图的两种搜索算法详解

    Java数据结构之图的两种搜索算法详解 引言 图是现实世界中最为普遍的现象之一,因此对于图的分析和操作是计算机科学和工程中最为重要的问题之一。在本文中,我们将对图结构的两种搜索算法进行详细讨论和研究,这些算法是图论研究的基本工具。 图的定义 在计算机科学和数学领域中,图是由若干个节点(或称为顶点)和它们之间的边组成的一种数据结构。 图的两种搜索算法 图的搜索…

    数据结构 2023年5月17日
    00
  • Java数据结构之栈与队列实例详解

    Java数据结构之栈与队列实例详解攻略 简介 栈和队列是常见的数据结构,在Java中也有对应的实现方式。本文将介绍栈和队列的概念、常见实现方式、应用场景和两个示例。 栈 概念 栈是一种具有后进先出(Last In First Out)特性的数据结构。栈可以使用数组或链表实现。 常见实现方式 基于数组的栈实现 使用数组作为底层存储结构实现栈时,需要注意栈顶指针…

    数据结构 2023年5月17日
    00
  • JavaScript数据结构链表知识详解

    JavaScript数据结构链表知识详解 什么是链表 链表是一种线性结构,相比于数组,它不需要一块连续的内存空间,而是通过指针将一组零散的内存块串联起来使用。链表只保持一个指向链表中第一个节点的引用,每个节点则有指向下一个节点的指针。 链表的实现 链表的实现方式有很多种,下面介绍一种简单的单向链表实现方式,其中每个节点包含一个value属性和一个next属性…

    数据结构 2023年5月17日
    00
  • C++数据结构与算法之反转链表的方法详解

    C++数据结构与算法之反转链表的方法详解 在C++中,反转链表是一种常见的数据结构与算法技巧。在本文中,我们将详细讲解反转链表的实现过程以及常见的两种反转方法。 基本定义 在开始讲述反转链表算法之前,我们先介绍一下链表的基本定义。 链表是一种数据结构,其中每个节点包含一个数据元素和一个指向下一个节点的指针。下面是一个简单的链表的节点结构定义: struct …

    数据结构 2023年5月17日
    00
  • redis中hash数据结构及说明

    Redis中Hash数据结构及说明 简介 Redis中的Hash是一个string类型的field和value的映射表,可以将多个键值对存储在一个数据结构中,适合于存储对象。 通过HASH数据结构,我们可以方便的对单个field进行增删改查操作,增加了程序编写的方便性。 命令 以下是Hash数据结构的基础命令: HSET 将哈希表 key 中的域 field…

    数据结构 2023年5月17日
    00
  • Java数据结构之常见排序算法(下)

    Java数据结构之常见排序算法(下) 前言 这是 Java 数据结构之常见排序算法的第二篇,本篇文章将继续介绍常见的排序算法。对于尚未了解基本排序算法的读者,可以先阅读 Java 数据结构之常见排序算法(上)。 快速排序 快速排序是一种使用分治思想的排序算法,其思路是将一个数组分为两个子数组,再对子数组进行排序,这个过程不断递归执行。在具体实现时,选择一个元…

    数据结构 2023年5月17日
    00
  • Javascript数据结构与算法之列表详解

    Javascript数据结构与算法之列表详解 简介 本文旨在讲解Javascript中数据结构和算法的列表。 列表定义和实现 列表是一组有序的数据,每个列表中的数据项称为元素。在Javascript中,列表可以用数组来实现。数组的好处是它能够存储任意类型的数据,而且可以根据需要动态地调整数组的大小。下面是一个创建列表的基本模板: function List(…

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