数据结构之链式二叉树详解

数据结构之链式二叉树详解

链式二叉树是一种基于链表的二叉树存储实现方式,相对于基于数组的存储方式更加灵活。本文将详细讲解如何实现链式二叉树及相关操作。

数据结构定义

链式二叉树的节点定义如下:

template<class T>
struct BinaryTreeNode
{
    T m_nValue; // 节点的值
    BinaryTreeNode* m_pLeft; // 左子节点
    BinaryTreeNode* m_pRight; // 右子节点
};

链式二叉树的定义如下:

template<class T>
class BinarySearchTree
{
public:
    BinarySearchTree();
    ~BinarySearchTree();

    void insert(const T& value); // 插入节点
    void remove(const T& value); // 删除节点
    BinaryTreeNode<T>* find(const T& value); // 查找节点
    BinaryTreeNode<T>* minimum() const; // 返回最小值节点
    BinaryTreeNode<T>* maximum() const; // 返回最大值节点
    void print() const; // 中序遍历
private:
    void destroy_tree(BinaryTreeNode<T>* leaf); // 删除树节点
    void insert(const T& value, BinaryTreeNode<T>*& leaf); // 插入节点
    void remove(const T& value, BinaryTreeNode<T>*& leaf); // 删除节点
    BinaryTreeNode<T>* find(const T& value, BinaryTreeNode<T>* leaf); // 查找节点
    BinaryTreeNode<T>* minimum(BinaryTreeNode<T>* leaf) const; // 返回最小值节点
    BinaryTreeNode<T>* maximum(BinaryTreeNode<T>* leaf) const; // 返回最大值节点
    void print(BinaryTreeNode<T>* leaf) const; // 中序遍历
    BinaryTreeNode<T>* root_;
};

插入节点

插入操作是链式二叉树中比较简单的操作,比较文本值,根据大小选择左子节点或右子节点进行插入。根据文本值大小判断节点的左右子树,若某个节点的左子树或右子树为空,则在该位置插入节点,否则利用递归进行插入操作。

代码实现如下:

template<class T>
void BinarySearchTree<T>::insert(const T& value)
{
    insert(value, root_);
}

template<class T>
void BinarySearchTree<T>::insert(const T& value, BinaryTreeNode<T>*& leaf)
{
    if (leaf == nullptr) {
        leaf = new BinaryTreeNode<T>();
        leaf->m_nValue = value;
        leaf->m_pLeft = nullptr;
        leaf->m_pRight = nullptr;
    } else if (value < leaf->m_nValue) {
        insert(value, leaf->m_pLeft);
    } else {
        insert(value, leaf->m_pRight);
    }
}

删除节点

删除操作需要分为三种情况:

  • 节点为叶子节点,直接删除即可。
  • 节点有一个子节点,将子节点替换该节点即可。
  • 节点有两个子节点,先找出该节点右子树中的最小值,将其替换该节点,再删除该最小值节点。

代码实现如下:

template<class T>
void BinarySearchTree<T>::remove(const T& value)
{
    remove(value, root_);
}

template<class T>
void BinarySearchTree<T>::remove(const T& value, BinaryTreeNode<T>*& leaf)
{
    if (leaf == nullptr) {
        return;
    }
    if (value < leaf->m_nValue) {
        remove(value, leaf->m_pLeft);
    } else if (value > leaf->m_nValue) {
        remove(value, leaf->m_pRight);
    } else {
        if (leaf->m_pLeft == nullptr && leaf->m_pRight == nullptr) {
            delete leaf;
            leaf = nullptr;
        } else if (leaf->m_pLeft == nullptr) {
            BinaryTreeNode<T>* temp = leaf->m_pRight;
            delete leaf;
            leaf = temp;
        } else if (leaf->m_pRight == nullptr) {
            BinaryTreeNode<T>* temp = leaf->m_pLeft;
            delete leaf;
            leaf = temp;
        } else {
            BinaryTreeNode<T>* temp = minimum(leaf->m_pRight);
            leaf->m_nValue = temp->m_nValue;
            remove(temp->m_nValue, leaf->m_pRight);
        }
    }
}

查找节点

查找操作也是基于链式二叉树的特点,利用文本值大小进行查找,若该节点值大于(小于)查找值,则在左子树中(右子树中)进行查找,否则查找值即为该节点值,返回之。

代码实现如下:

template<class T>
BinaryTreeNode<T>* BinarySearchTree<T>::find(const T& value)
{
    return find(value, root_);
}

template<class T>
BinaryTreeNode<T>* BinarySearchTree<T>::find(const T& value, BinaryTreeNode<T>* leaf)
{
    if (leaf == nullptr) {
        return nullptr;
    }
    if (value < leaf->m_nValue) {
        return find(value, leaf->m_pLeft);
    } else if (value > leaf->m_nValue) {
        return find(value, leaf->m_pRight);
    } else {
        return leaf;
    }
}

返回最小值节点和最大值节点

返回最小值节点和最大值节点同样是基于链式二叉树的特点,分别在左子树上和右子树上不断向下寻找,直到到达叶子节点。

代码实现如下:

template<class T>
BinaryTreeNode<T>* BinarySearchTree<T>::minimum() const
{
    return minimum(root_);
}

template<class T>
BinaryTreeNode<T>* BinarySearchTree<T>::minimum(BinaryTreeNode<T>* leaf) const
{
    if (leaf == nullptr) {
        return nullptr;
    }
    if (leaf->m_pLeft == nullptr) {
        return leaf;
    } else {
        return minimum(leaf->m_pLeft);
    }
}

template<class T>
BinaryTreeNode<T>* BinarySearchTree<T>::maximum() const
{
    return maximum(root_);
}

template<class T>
BinaryTreeNode<T>* BinarySearchTree<T>::maximum(BinaryTreeNode<T>* leaf) const
{
    if (leaf == nullptr) {
        return nullptr;
    }
    if (leaf->m_pRight == nullptr) {
        return leaf;
    } else {
        return maximum(leaf->m_pRight);
    }
}

中序遍历

中序遍历是将整棵树按照从小到大的顺序输出。

template<class T>
void BinarySearchTree<T>::print() const
{
    print(root_);
    std::cout << std::endl;
}

template<class T>
void BinarySearchTree<T>::print(BinaryTreeNode<T>* leaf) const
{
    if (leaf == nullptr) {
        return;
    }
    print(leaf->m_pLeft);
    std::cout << leaf->m_nValue << " ";
    print(leaf->m_pRight);
}

示例说明

BinarySearchTree<int> t;
t.insert(5);
t.insert(3);
t.insert(2);
t.insert(4);
t.insert(7);
t.insert(6);
t.insert(8);
t.print(); // 2 3 4 5 6 7 8
t.remove(5);
t.print(); // 2 3 4 6 7 8
t.find(6); // 返回6节点
t.minimum(); // 返回值为2的节点
t.maximum(); // 返回值为8的节点

以上代码示例展示了链式二叉树的插入、删除、查找、返回最小值节点、返回最大值节点及中序遍历操作。

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

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • delphi 组件安装教程详解

    Delphi是一种面向对象的编程语言,常用于Windows平台的应用程序开发。在Delphi中,组件是一种可重用的代码模块,可以大大提高开发效率。在本文中,我们将详细介绍Delphi组件的安装教程,并提供两个示例说明。 Delphi组件安装教程 步骤1:下载组件 首先,我们需要从组件提供商的网站上下载所需的组件。通常,组件提供商会提供一个安装程序或一个ZIP…

    other 2023年5月5日
    00
  • java实现table添加右键点击事件监听操作示例

    下面将为您详细讲解Java实现Table添加右键点击事件监听的完整攻略。 准备工作 在开始之前,您需要进行以下准备工作: 确保您已经熟悉Java语言,了解如何使用Swing进行图形化界面的开发。 在您的开发环境中安装好了Java开发工具包(JDK)以及集成开发环境(IDE)。 添加右键点击事件监听 下面的步骤将会详细讲解如何添加右键点击事件的监听。假设我们有…

    other 2023年6月27日
    00
  • C语言基础 strlen 函数

    C语言基础 strlen 函数 简介 strlen函数是C语言中非常常用的字符串函数之一,用于计算一个字符串的长度。其原型为: size_t strlen(const char *str); 函数原型的返回值类型为 size_t, size_t 是一个无符号整数类型,其大小通常与 unsigned int 相同,用于保证变量的值为正数。函数的参数是一个指向字…

    other 2023年6月27日
    00
  • vs2010打包安装包带数据库

    VS2010打包安装包带数据库 在软件开发过程中,经常需要将开发完成的程序打包成安装包进行发布。为了方便用户的安装,可以将程序的依赖项也打包进去,比如数据库。本文将介绍如何使用VS2010打包安装包并将数据库一起打包。 准备工作 在开始之前,需要安装VS2010和SQL Server 2008 R2(假设你的程序是基于该版本的数据库开发的)。同时,需要确保你…

    其他 2023年3月28日
    00
  • 如何禁止QQ修改浏览器的鼠标右键菜单

    下面是如何禁止QQ修改浏览器的鼠标右键菜单的完整攻略。 1. 为什么禁止QQ修改浏览器的鼠标右键菜单 QQ浏览器会默认将鼠标右键菜单设置为其自己的菜单,这种行为可能影响用户的浏览体验。有些用户可能更喜欢使用浏览器默认的右键菜单,因此需要对QQ浏览器进行设置。 2. 禁止QQ修改浏览器的鼠标右键菜单的方法 方法1:通过QQ浏览器设置 打开QQ浏览器,点击浏览器…

    other 2023年6月27日
    00
  • 【超分辨率】—图像超分辨率(Super-Resolution)技术研究

    【超分辨率】—图像超分辨率(Super-Resolution)技术研究 什么是图像超分辨率技术 图像超分辨率技术是一种将低分辨率图像转换为高分辨率图像的技术。由于在实际应用中,拍摄的图像像素不够高,容易导致图像模糊不清。而超分辨率技术可以通过利用图像中的高频信息,将低分辨率图像转换为高分辨率图像,从而提高图像的清晰度。 图像超分辨率技术的原理 图像超分辨率技…

    其他 2023年3月28日
    00
  • eclipse启动出现“failed to load the jni shared library”问题解决

    Eclipse启动出现\”failed to load the jni shared library\”问题解决攻略 当你尝试启动Eclipse时,可能会遇到\”failed to load the jni shared library\”错误。这个错误通常是由于Eclipse无法找到或加载Java Native Interface(JNI)共享库引起的。下…

    other 2023年8月3日
    00
  • JavaScript声明变量名的语法规则

    在JavaScript中,声明变量的语法规则非常重要,它决定了变量名的有效性和使用方式。下面是一个详细的攻略,帮助您了解JavaScript中声明变量名的语法规则。 变量名的语法规则 变量名只能包含字母、数字、美元符号($)和下划线(_),不能包含空格或其他特殊字符。 变量名必须以字母、美元符号或下划线开头,不能以数字开头。 变量名区分大小写,例如myVar…

    other 2023年8月8日
    00
合作推广
合作推广
分享本页
返回顶部