纯C++代码详解二叉树相关操作

纯C++代码详解二叉树相关操作

介绍

二叉树是一种非常常见的数据结构,适用于处理需要具有层级关系的数据。在本文中,我们将详细讲解如何使用C++来实现二叉树的基本操作,包括创建、遍历、插入、删除等。

创建二叉树

定义二叉树节点

在C++中实现二叉树的概念,需要先定义二叉树节点的结构,代码如下:

struct BinaryTreeNode
{
    int value; // 节点的值
    BinaryTreeNode* left; // 左子节点
    BinaryTreeNode* right; // 右子节点
};

创建二叉树

创建一个二叉树对象,需要一个根节点,代码如下:

BinaryTreeNode* root = new BinaryTreeNode;
root->value = 1;
root->left = new BinaryTreeNode;
root->left->value = 2;
root->left->left = NULL;
root->left->right = NULL;
root->right = new BinaryTreeNode;
root->right->value = 3;
root->right->left = NULL;
root->right->right = NULL;

这个二叉树的结构是这样的:

      1
     / \
    2   3

遍历二叉树

遍历二叉树有三种常见的方法:前序遍历、中序遍历、后序遍历。以下分别为三种遍历方式的代码。

前序遍历

前序遍历的顺序是:根节点 -> 左子树 -> 右子树。

void PreOrderTraversal(BinaryTreeNode* node)
{
    if(node)
    {
        cout << node->value << "->";
        PreOrderTraversal(node->left);
        PreOrderTraversal(node->right);
    }
}

中序遍历

中序遍历的顺序是:左子树 -> 根节点 -> 右子树。

void InOrderTraversal(BinaryTreeNode* node)
{
    if(node)
    {
        InOrderTraversal(node->left);
        cout << node->value << "->";
        InOrderTraversal(node->right);
    }
}

后序遍历

后序遍历的顺序是:左子树 -> 右子树 -> 根节点。

void PostOrderTraversal(BinaryTreeNode* node)
{
    if(node)
    {
        PostOrderTraversal(node->left);
        PostOrderTraversal(node->right);
        cout << node->value << "->";
    }
}

插入节点

插入左子节点

如果一个节点没有左子节点,我们可以通过如下代码给它插入一个:

BinaryTreeNode* node = new BinaryTreeNode;
node->value = 4;
node->left = NULL;
node->right = NULL;

root->left->left = node;

这个二叉树的结构变成了这样:

      1
     / \
    2   3
   /
  4

插入右子节点

如果一个节点没有右子节点,我们可以通过如下代码给它插入一个:

BinaryTreeNode* node = new BinaryTreeNode;
node->value = 5;
node->left = NULL;
node->right = NULL;

root->left->right = node;

这个二叉树的结构变成了这样:

      1
     / \
    2   3
   / \
  4   5

删除节点

删除叶子节点

如果要删除一个叶子节点,只需要把它的父节点的指针指向NULL即可。

delete root->left->right;
root->left->right = NULL;

这个二叉树的结构变成了这样:

      1
     / \
    2   3
   /
  4

删除非叶子节点

删除非叶子节点需要注意两种情况:被删除节点有一个子节点或两个子节点。对于只有一个子节点的节点,我们将其子节点向上移动即可。对于有两个子节点的节点,我们需要找到其后继节点,用后继节点替换被删除节点。

// 寻找一个节点的后继节点
BinaryTreeNode* GetSuccessor(BinaryTreeNode* node)
{
    if(node->right == NULL)
        return NULL;
    BinaryTreeNode* p = node->right;
    while(p->left != NULL)
        p = p->left;
    return p;
}

// 删除节点
void DeleteNode(BinaryTreeNode* root, int value)
{
    if(!root)
        return;
    if(root->value == value)
    {
        if(!root->left && !root->right)
        {
            delete root;
            root = NULL;
        }
        else if(root->left && !root->right)
        {
            BinaryTreeNode* temp = root->left;
            *root = *temp;
            delete temp;
        }
        else if(!root->left && root->right)
        {
            BinaryTreeNode* temp = root->right;
            *root = *temp;
            delete temp;
        }
        else
        {
            BinaryTreeNode* successor = GetSuccessor(root);
            root->value = successor->value;
            DeleteNode(root->right, successor->value);
        }
    }
    else if(root->value > value)
        DeleteNode(root->left, value);
    else
        DeleteNode(root->right, value);
}

示例

下面是一个完整的二叉树的示例,显示了如何创建、遍历、插入和删除二叉树节点。

#include <iostream>

using namespace std;

struct BinaryTreeNode
{
    int value;
    BinaryTreeNode* left;
    BinaryTreeNode* right;
};

void PreOrderTraversal(BinaryTreeNode* node)
{
    if(node)
    {
        cout << node->value << "->";
        PreOrderTraversal(node->left);
        PreOrderTraversal(node->right);
    }
}

void InOrderTraversal(BinaryTreeNode* node)
{
    if(node)
    {
        InOrderTraversal(node->left);
        cout << node->value << "->";
        InOrderTraversal(node->right);
    }
}

void PostOrderTraversal(BinaryTreeNode* node)
{
    if(node)
    {
        PostOrderTraversal(node->left);
        PostOrderTraversal(node->right);
        cout << node->value << "->";
    }
}

BinaryTreeNode* GetSuccessor(BinaryTreeNode* node)
{
    if(node->right == NULL)
        return NULL;
    BinaryTreeNode* p = node->right;
    while(p->left != NULL)
        p = p->left;
    return p;
}

void DeleteNode(BinaryTreeNode* root, int value)
{
    if(!root)
        return;
    if(root->value == value)
    {
        if(!root->left && !root->right)
        {
            delete root;
            root = NULL;
        }
        else if(root->left && !root->right)
        {
            BinaryTreeNode* temp = root->left;
            *root = *temp;
            delete temp;
        }
        else if(!root->left && root->right)
        {
            BinaryTreeNode* temp = root->right;
            *root = *temp;
            delete temp;
        }
        else
        {
            BinaryTreeNode* successor = GetSuccessor(root);
            root->value = successor->value;
            DeleteNode(root->right, successor->value);
        }
    }
    else if(root->value > value)
        DeleteNode(root->left, value);
    else
        DeleteNode(root->right, value);
}

int main()
{
    BinaryTreeNode* root = new BinaryTreeNode;
    root->value = 1;
    root->left = new BinaryTreeNode;
    root->left->value = 2;
    root->left->left = NULL;
    root->left->right = NULL;
    root->right = new BinaryTreeNode;
    root->right->value = 3;
    root->right->left = NULL;
    root->right->right = NULL;

    cout << "preorder traversal: ";
    PreOrderTraversal(root);
    cout << endl;

    cout << "inorder traversal: ";
    InOrderTraversal(root);
    cout << endl;

    cout << "postorder traversal: ";
    PostOrderTraversal(root);
    cout << endl;

    BinaryTreeNode* node = new BinaryTreeNode;
    node->value = 4;
    node->left = NULL;
    node->right = NULL;

    root->left->left = node;

    cout << "preorder traversal after inserting 4: ";
    PreOrderTraversal(root);
    cout << endl;

    BinaryTreeNode* node2 = new BinaryTreeNode;
    node2->value = 5;
    node2->left = NULL;
    node2->right = NULL;

    root->left->right = node2;

    cout << "preorder traversal after inserting 5: ";
    PreOrderTraversal(root);
    cout << endl;

    DeleteNode(root, 2);

    cout << "preorder traversal after deleting 2: ";
    PreOrderTraversal(root);
    cout << endl;

    return 0;
}

这个程序输出的结果如下:

preorder traversal: 1->2->3->
inorder traversal: 2->1->3->
postorder traversal: 2->3->1->
preorder traversal after inserting 4: 1->2->4->3->
preorder traversal after inserting 5: 1->2->4->5->3->
preorder traversal after deleting 2: 1->4->5->3->

可以看到,通过这个代码示例,我们实现了(1) 创建一个二叉树;(2) 实现三种遍历方式;(3) 向二叉树中插入节点;(4) 删除二叉树中的节点。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:纯C++代码详解二叉树相关操作 - Python技术站

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

相关文章

  • 使用go实现常见的数据结构

    下面我将详细讲解使用go实现常见的数据结构的完整攻略。 1. 概述 数据结构是计算机程序设计中一个非常重要的概念,常见的有数组、链表、栈、队列、树、图等。本文主要介绍如何使用Go实现常见的数据结构。 2. 数组 数组是最简单、最基本的数据结构之一,它在Go中的实现非常简单,可以用以下代码片段表示: // 定义一个长度为10的整型数组 var arr [10]…

    数据结构 2023年5月17日
    00
  • 使用C语言构建基本的二叉树数据结构

    下面是使用C语言构建二叉树数据结构的步骤和示例: 1. 定义二叉树结构体类型 定义一个二叉树的结构体,包含节点值、左右子节点等信息: typedef struct TreeNode { int val; struct TreeNode* left; struct TreeNode* right; } TreeNode; 2. 实现创建二叉树的函数 实现一个函…

    数据结构 2023年5月17日
    00
  • 自制PHP框架之模型与数据库

    很好,下面我将为您详细讲解如何自制PHP框架中的模型与数据库部分。 什么是模型和数据库? 在讲解自制PHP框架的模型和数据库前,我们需要先了解什么是模型和数据库。在PHP框架架构中,模型是用来操作数据库的一种机制,用来处理对数据表的增删改查等操作,并且与数据库的连接是一定的。而数据库是一种数据存储工具,用于存储数据并提供数据操作的方法,例如数据的增删改查等。…

    数据结构 2023年5月17日
    00
  • c语言数据结构之并查集 总结

    C语言数据结构之并查集总结 简介 并查集,也称作不相交集合,是一种树型的数据结构。并查集用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。 并查集只有两个操作: find:确定某个元素属于哪个子集。它可以被用来确定两个元素是否属于同一子集。 union:将两个子集合并成同一个集合。 基本实现 以快速查找find和…

    数据结构 2023年5月17日
    00
  • JavaScript数据结构之链表的实现

    JavaScript数据结构之链表的实现 什么是链表 链表是一种线性数据结构,其中的元素在内存中不连续地存储,每个元素通常由一个存储元素本身的节点和一个指向下一个元素的引用组成。相比较于数组,链表具有如下优缺点: 优点:动态地添加或删除元素时,无需移动其它元素。(数组则需要移动其它元素) 缺点:不能随机地访问某个元素,必须从头开始顺序遍历。(而数组可以通过索…

    数据结构 2023年5月17日
    00
  • C语言超详细讲解双向带头循环链表

    C语言双向带头循环链表 基本概念 带头双向循环链表是指在双向循环链表的基础上,在头节点前面添加一个头结点。这个头结点不存储任何数据,只是为了方便对链表进行操作。循环链表则是在单向或双向链表的基础上,使链表的头节点与尾节点相连,形成一个环。 综合这两种链表,就构成了“双向带头循环链表”这种数据结构。双向带头循环链表是一种灵活性较高的数据结构,支持前插、后插、前…

    数据结构 2023年5月17日
    00
  • C++ 数据结构线性表-数组实现

    C++ 数据结构线性表-数组实现 什么是线性表 线性表,简单来说,就是一种有序的数据结构,数据元素起来往往构成一列,比如数组、链表等等。 数组实现线性表 数组是一种容器,它可以存储相同类型的数据元素。使用数组实现线性表,就是将数据元素按照一定的顺序依次存储在数组中。 数组实现线性表的基本思路 定义一个数组,用来存储数据元素; 定义一个变量,用来记录线性表中元…

    数据结构 2023年5月17日
    00
  • C语言创建和操作单链表数据结构的实例教程

    C语言创建和操作单链表数据结构的实例教程 什么是单链表 单链表是一种常见的动态数据结构,它由一个个节点组成,每个节点包含范围内的数据和指向下一个节点的指针。单链表通常用于需要频繁插入删除节点的情况。 单链表的创建和操作步骤 创建单链表 定义一个链表节点结构体,结构体中包含要存储的数据和指向下一个节点的指针。 定义一个指向链表头部的指针,如果链表为空,则指针为…

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