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

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

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

数据结构定义

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

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日

相关文章

  • java中重定向

    Java中重定向 在Java中,我们可以使用重定向(Redirect)来实现跳转页面。重定向是一种服务器端的跳转方式,它可以将客户端的请求重定向到另一个页面,同时还可以带上参数。 在Java中,我们一般使用ServletResponse的sendRedirect()方法来实现重定向。下面是一个简单的例子: response.sendRedirect(&quo…

    其他 2023年3月28日
    00
  • Notepad++字符空行替换技巧四则新手进阶

    Notepad++字符空行替换技巧四则新手进阶攻略 Notepad++是一款功能强大的文本编辑器,提供了许多实用的功能,其中字符空行替换技巧是新手进阶的重要一环。本攻略将详细介绍如何使用Notepad++进行字符空行替换,并提供两个示例说明。 步骤一:打开Notepad++ 首先,确保你已经安装了最新版本的Notepad++。然后,打开Notepad++编辑…

    other 2023年8月18日
    00
  • windowsthinpc体验&语言包更改(win7included)

    Windows Thin PC是一款基于Windows 7的轻量级操作系统,专门为低端硬件设备和虚拟化环境而设计。下面是Windows Thin PC体验和语言包更改的完整攻略,包括两个示例。 示例一:安装Windows Thin PC 下载Windows Thin PC ISO文件。 使用ISO文件创建启动盘。 将启动盘插入计算机并启动计算机。 在安装向导…

    other 2023年5月9日
    00
  • HTTP长连接与短连接使用方法及测试详解

    HTTP长连接与短连接使用方法及测试详解 一、概述 HTTP(超文本传输协议)是一种基于TCP/IP协议的传输协议。与TCP连接的建立和关闭需要时间,如果每一次请求都要重新建立连接,频繁的三次握手可能会浪费大量的时间和带宽。 HTTP长连接和短连接在HTTP协议中必须要重点讨论的问题。长连接和短连接是指客户端和服务器建立的TCP连接的存活时间。 二、长连接和…

    other 2023年6月27日
    00
  • 利用Java如何实现将二维数组转化为链式储存

    将二维数组转化为链式储存的过程需要以下步骤: 定义链表节点 每个链表节点需要保存数组元素值及其行列信息 可以使用Java中的类或结构体来实现 创建一个链表并将节点依次添加进去 遍历二维数组的每个元素,将元素的值和行列信息封装成链表节点,然后将节点添加到链表的尾部 可以使用Java中的链表或其他数据结构来存储节点 下面是一个示例代码: public class…

    other 2023年6月27日
    00
  • 字符串正则替换replace第二个参数是函数的问题

    在进行字符串正则替换时,我们可以使用replace方法的第二个参数来传递一个函数,该函数将被用于计算替换字符串。这种方式可以让我们更加灵活地进行替换操作,例如,可以根据匹配到的内容动态生成替换字符串。下面是使用replace方法进行正则替换的完整攻略,包含两个示例说明。 步骤 引入re模块:我们需要引入Python的re模块以便使用正则表达式。 python…

    other 2023年5月6日
    00
  • 配置中心apollo的设计原理

    配置中心Apollo的设计原理 Apollo是携程开源的一款分布式配置中心,它提供了统一的配置管理、配置发布、配置等功能。本文将介绍Apollo的设计原理,包括如何实现配置动态更新、何保证配置的高可用性等。 Apollo的核心概念 Apollo的设计原理基于以下几个核心概念: Namespace 是Apollo中的一个概念,它代表了一组相关的配置项。每个Na…

    other 2023年5月7日
    00
  • 纯真ip数据库格式详解

    纯真IP数据库是一种常用的IP地址归属地查询工具,以下是纯真IP数据库格式的详解: 下载纯真IP数据库 在纯真IP数据库官网(http://www.cz88.net/)上下载最新版的IP数据库,通常包括两个文件:QQWry.dat和QQWry.idx。 IP数据库格式 纯真IP数据库采用的是固定长度的数据格式,每条记录的长度为7个字节,格式如下: | 4字节…

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