数据结构——树

树的概念:

                                 图1                                                                  图2

        图1中是我们现实生活中的树,根在下,叶子和分支在上,而在计算机中的树是图二中的样子,也就是现实生活中的树倒过来的样子,根在上,叶子和分子在下;而具体是什么样子呢如图3:

   

图3

        树的的性质:

        1.一颗树有且只有一个根节点;

        2.根节点没有前驱结点,也就是没有父节点,而其他结点有且只有一个父节点;

        3.结点代表集合,边代表关系,那么根节点代表这颗树的全集,其他结点都代表这颗树的子集,并且被根节点所包含;

        4.一个结点有几条边,也就是几个子孩子,那他的度就为几,比如图3中的1结点度为3,3结点度为0;

        5.一颗树的节点数量等于所有结点的度+1,+1是因为根节点没有父节点,+1就是加的根结点;

        6.树的深度,从上往下看,比如7结点的深度为3,3结点的深度为2;

        7.树的高度,从下往上看,比如7结点的高度为1,3结点的高度为2;

 二叉树:

        这文章主要讲二叉树,因为在数据结构中用的树,最多的也是二叉树,可以通过二叉树的代码,来转换成普通树的代码也是一样的;

结构定义

物理结构

        二叉树是树的一种树形结构,它的特点就是,一个结点最多只有两个子孩子结点(下文中可能会分为左右孩子),并且左右还在结点不能交换顺序,不能颠倒;

        其实链表也可以看作一颗树,只是这颗树的每一个结点只有一个子孩子,那么链表的结构定义是:


typedef struct Node {//结点定义void val;//值域,可以是int,char等等类型struct Node *next;//指针域,用来存下一个结点的地址的
} Node;

        那么二叉树他有两个子孩子,就再多定义一个指针域,指向另一个子孩子:


typedef struct Node {//结点定义void val;//值域,可以是int,char等等类型struct Node *lchild, *rchild;//指针域,用来存下一个结点的地址的,分别为左孩子和右孩子
} Node;

逻辑结构

        他的逻辑结构就是它最多只有两个子孩子,那么二叉树中每个结点的度小于等于2;

二叉树的性质

        1.每个结点的度最多为2;

        2.度为0的结点个数比度为2的结点多一个N_0 = N_2 + 1

        3.非空的二叉树,第i层的结点数最多为:2^{i-1}

        4.高度为h的二叉树,节点数最多为:2^h - 1

        5.满二叉树:也就是除了度0的结点,都是度为2的结点,它的结点数量就是2^h - 1(这是一种特殊的二叉树);需要注意的是,满二叉树肯定是完全二叉树,而完全二叉树不一定是满二叉树。

        6.完全二叉树:在完全二叉树中叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部;也就是说,完全二叉树如果有一个结点没有左子树,但有右子树那么这一定不是完全二叉树;

        7.排序二叉树:根节点的值大于左子树,小于右子树的值;

        8.平衡二叉树:对于排序二叉树的优化,左右子树中的任意结点高度差不大于1;

结构操作:

        对于树的操作,会用到很多递归的编程技巧;递归就是函数调用函数本身,将一个较大的问题分为较小的问题进行处理,然后通过较小问题的返回进行回溯到最开始调用第一次时得到最终结果;

递归举例

        举一个经典的递归问题,爬楼梯一次可以上1层或2层,爬20层有几种方式;

        先分析爬1层只有一种办法,2层有两种方法,而这两种就是递归分为的最小问题;

        而f(n) = f(n - 1) + f(n - 2),n为爬的层数,为什么这个公式成立,先把20层拿进去,f(20) = f(19) + f(18),而减一就是从19爬到20,减二就是18爬到20,倒过来想,能爬到20层的只有这两个方法,那爬20层的方法总数就等于它们俩的方法总数的和,所这样一直分化下去,直到只爬一层,两层这样问题就分到了最小,也就是递归出口,这样进行返回,回溯最终得到结果;

        代码实现如下:

#include <stdio.h>int f(int n) {if (n <= 2) return n;//递归出口return f(n - 1) + f(n - 2);//开始递归直到递归到出口
}int main() {printf("%d\n", f(20)); return 0;
}

        现在有了一点递归的概念后,开始实现二叉树的插入:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>typedef struct Node {//结构定义结点int val;struct Node *lchild, *rchild;
} Node;typedef struct Tree {//定义树int n;        Node *root;
} Tree;Node *getNewNode(int val) {//获取新节点Node *n = (Node *)malloc(sizeof(Node));n->val = val;n->lchild = n->rchild = NULL;return n;
}Tree *getNewTree() {//获取新树Tree *tree = (Tree *)malloc(sizeof(Tree));tree->n = 0;tree->root = NULL;return tree;
}Node * __insert(Node *root, int val, int *ret) {//添加结点操作if (!root) {*ret = 1;return getNewNode(val);}if (val < root->val) root->lchild = __insert(root->lchild, val, ret);else  root->rchild = __insert(root->rchild, val, ret);return root;
}void insert(Tree *tree, int val) {//添加结点int flag = 0;tree->root = __insert(tree->root, val, &flag);tree->n += flag;return ;
jvoid pre_output(Node *root) {// 先序遍历if (!root) return ;printf("%d(", root->val);pre_output(root->lchild);printf(", ");pre_output(root->rchild);printf(")");return ;
}void output(Tree *tree) {//输出树的结果pre_output(tree->root);return ;
}void clearNode(Node *root) {//递归归还空间if (!root) return ;clearNode(root->lchild);clearNode(root->rchild);free(root);return ;
}void clear(Tree *tree) {if (!tree);clearNode(tree->root);free(tree);return ;
}int main() {//测试srand(time(0));Tree *tree = getNewTree();for (int i = 0; i < 10; i++) {int val = rand() % 100;  insert(tree, val);}output(tree);putchar(10);clear(tree);return 0;}

        这里只实现了,插入的操作,删除的操作,在后面的文章中讲排序二叉树中会讲到;

遍历二叉树

        在上面的代码中pre_output函数的输出就是先序遍历,先序遍历是如何遍历的,根节点左子树,右子树;中序遍历先遍历左子树在遍历根结点最后遍历右子树;后序遍历就是左子树,右子树,根节点;

图4

        对图中的树进行先序遍历的结果为:1245367;

        对图中的树进行中序遍历的结果为:4251637;

        对图中的树进行后序遍历的结果为:4526731;

        先序遍历的代码:

        

void pre_orderNode(Node *root) {if (!root) return ;printf("%d ", root->data);//先输出根节点pre_orderNode(root->lchild);//遍历左子树pre_orderNode(root->rchild);//遍历右子树return ;
}void pre_order(Tree *tree) {printf("pre_order : ");pre_orderNode(tree->root);printf("\n");return ;
}

        中序遍历代码:

        

void in_orderNode(Node *root) {if (!root) return ;in_orderNode(root->lchild);//先遍历左子树printf("%d ", root->data);//在打印根节点的值in_orderNode(root->rchild);//在遍历右子树return ;
}void in_order(Tree *tree) {printf("in_order : ");in_orderNode(tree->root);printf("\n");return ;
}

        后序遍历代码:

void post_orderNode(Node *root) {if (!root) return ;post_orderNode(root->lchild);//先遍历左子树post_orderNode(root->rchild);//在遍历右子树printf("%d ", root->data);//最终打印根节点值return ;
}void post_order(Tree *tree) {printf("post_order : ");post_orderNode(tree->root);printf("\n");return ;
}

        可能这些内容不够完善,如果有什么问题可以提出来,麻烦各位大哥了;

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue学习笔记一(2019)

1.Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器&#xff0c;它包含着你的应用…

android 输入法demo

背景&#xff1a; 一个简单的android输入法demo&#xff0c;支持输入png、gif&#xff0c;jpeg、webp等格式。 此示例演示如何编写一个应用程序&#xff0c;该应用程序接受使用 Commit Content API 从键盘发送的丰富内容&#xff08;例如图像&#xff09;。 用户通常希望通过表…

day-03 基于TCP的服务器端/客户端

一.理解TCP和UDP TCP&#xff08;Transmission Control Protocol&#xff09;和UDP&#xff08;User Datagram Protocol&#xff09;是两种常见的传输层协议&#xff0c;用于在计算机网络中提供可靠的数据传输。 1.TCP&#xff1a; 连接导向&#xff1a;TCP是一种面向连接的…

Android 蓝牙开发( 四 )

前言 上一篇文章给大家分享了Kotlin版的Android蓝牙的基础知识和基础用法&#xff0c;不过上一篇都是一些零散碎片化的程序&#xff0c;&#xff0c;这一篇给大家分享Android蓝牙开发实战项目KotlinCompose的初步使用 效果演示 : Android Compose 蓝牙开发 Android蓝牙实战开发…

Sqoop实操案例-互联网招聘数据迁移

&#x1f947;&#x1f947;【大数据学习记录篇】-持续更新中~&#x1f947;&#x1f947; 个人主页&#xff1a;beixi 本文章收录于专栏&#xff08;点击传送&#xff09;&#xff1a;【大数据学习】 &#x1f493;&#x1f493;持续更新中&#xff0c;感谢各位前辈朋友们支持…

【实操干货】如何开始用Qt Widgets编程?(四)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 在本文中&#xff0…

Android 蓝牙开发( 二 )

前言 上一篇文章给大家分享了Android蓝牙的基础知识和基础用法&#xff0c;不过上一篇都是一些零散碎片化的程序&#xff0c;这一篇给大家分享Android蓝牙开发实战项目的初步使用 效果演示 : Android蓝牙搜索&#xff0c;配对&#xff0c;连接&#xff0c;通信 Android蓝牙实…

数据分析师职业发展道路,工作内容是什么?

很多同学问&#xff0c;参加数据分析就业班后之的就业发展道路是怎样的&#xff0c;工作又能做什么呢&#xff1f; 市面上的常见的工作类型有有运营类、技术类及分析类等&#xff0c;可以根据自己的意愿去做适合自己的工作&#xff0c;但是任何工作其实都是需要一技之长。…

基于实例的学习方法

基于实例的学习方法 动机基本概念基于实例的学习基于实例的概念表示 1. 最近邻最近邻的例子理论结果最近邻&#xff08;1- NN&#xff09;:解释问题 K-近邻(KNN)KNN讨论1 &#xff1a;距离度量KNN 讨论2&#xff1a;属性KNN:属性归一化KNN:属性加权 KNN讨论3:连续取值目标函数K…

ssh常用操作

ssh常用操作 SSH是一种安全协议&#xff0c;ssh是该协议的客户端程序&#xff0c;openssh-server则是该协议的服务端程序 常用系统都自带了ssh客户端程序&#xff0c;服务端程序则可能要安装 密码远程登陆 前提&#xff1a;服务器安装了openssh-server&#xff0c;未安装时…

自定义TimeLine实现卡拉OK轨

系列文章目录 自定义TimeLine 自定义TimeLine 系列文章目录前言正文UI部分代码部分Data&#xff08;数据&#xff09;Clip&#xff08;片段&#xff09;Track&#xff08;轨道&#xff09;Mixer&#xff08;混合&#xff09;被控制物体 总结 前言 自定义TimeLine实际上就是自定…

Android安卓webview,网页端生成安卓项目(极速生成)教程

Android安卓webview&#xff0c;网页端生成安卓项目&#xff08;极速生成&#xff09;教程 一&#xff0c;前言 当自己做了一个PC端的页面&#xff0c;也就是前端的页面&#xff0c;或者已经上服的页面&#xff0c;但也想生成一个安卓端供用户使用&#xff0c;本教程详细讲解…

人员位置管理,点亮矿山安全之路

矿山作为一个高危行业&#xff0c;安全问题一直备受关注。人员定位置管理是现代矿山安全管理的重要一环&#xff0c;可以帮助企业更好地实现对人员的实时监控和管理。因此&#xff0c;矿山人员位置管理系统对于矿山安全生产和管理非常重要&#xff0c;可以帮助减少安全事故的发…

BEVFusion复现 (Ubuntu RTX3090)

https://github.com/ADLab-AutoDrive/BEVFusion 1.环境安装 我的机器是RTX3090&#xff0c;CUDA11.1 1.创建虚拟环境 conda create -n bevfusion python3.8.3 2.安装PyTorch 和 torchvision pip install torch1.8.0cu111 torchvision0.9.0cu111 torchaudio0.8.0 -f https://…

Java中的动态代理(JDK Proxy VS CGLib)

前言 动态代理可以说是Java基础中一个比较重要的内容&#xff0c;这块内容关系到Spring框架中的AOP实现原理&#xff0c;所以特别写了一篇作为个人对这块知识的总结。这部分内容主要包括&#xff1a;JDK Proxy和CGLib的基本介绍、二者的实现原理、代码示例等。 什么是动态代理…

C# 如何将使用的Dll嵌入到.exe应用程序中?

文章目录 前言详细实操简要步骤 前言 有没有想自己开发的exe保留一点神秘&#xff0c;不想让他人知道软件使用了哪些dll; 又或许是客户觉得一个软件里面的dll文件太多了&#xff0c;能不能简单一点&#xff0c;直接双击.exe就可以直接运行了&#xff0c;别搞那么多乱七八糟的。…

Three.js相机参数及Z-Fighting问题的解决方案

本主题讨论透视相机以及如何为远距离环境设置合适的视锥体。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 透视相机是一种投影模式&#xff0c;旨在模仿人类在现实世界中看待事物的方式。 这是渲染 3D 场景最常用的投影模式。 - three.js 如果你看一下 Three.js 文档…

优思学院|六西格玛中的概率分布有哪些?

为什么概率分布重要&#xff1f; 概率分布是统计学中一个重要的概念&#xff0c;它帮助我们理解随机变量的分布情况以及与之相关的概率。在面对具体问题时&#xff0c;了解概率分布可以帮助我们选择适当的检验或分析策略&#xff0c;以解决问题并做出合理的决策。 常见的概率…

【二】kubernetes master单节点拓展为集群

#服务器 #部署 #云原生 #k8s 一、 前言 一、ubuntu20.04上搭建containerd版&#xff08; 1.2.4 以上&#xff09;k8s及kuboard V3 接上文中&#xff0c;我们已经部署好了单节点master的k8s集群&#xff0c;在生产环境中&#xff0c;单节点的master肯定是不行的&#xff0c;那…

科技探究之旅--亲子研学活动

2023年8月26日&#xff0c;广州市从化区齐家社会工作服务中心&#xff08;以下简称“齐家”&#xff09;的“星乐园-乡村儿童公益辅导服务项目”组织了新开村及西湖村助学点24对亲子到广州市白云区文搏3D打印基地进行“科技探究之旅--亲子研学”活动&#xff0c;旨在发现、点燃…