(浙大陈越版)数据结构 第三章 树(上) 3.1 树和树的表示

news2024/11/28 0:55:59

目录

3.1.1 引子(顺序查找)

什么是树

查找

3.1.2 引子 二分查找例子(BinarySearch)

二分查找

3.1.3 引子 二分查找实现

二分查找代码

二分查找的启示

3.1.4 树的定义

一些基本术语:

3.1.5 树的表示


3.1.1 引子(顺序查找)

什么是树

在客观世界上许多事物存在层次关系。如人类社会的家谱、社会组织管理结构、省市县乡镇的分级,计算机中为了还原这种结构,使用了树这种数据结构。

那么为什么要使用这种层次结构?因为分层组织在数据管理方面有更高的效率

下面以数据管理的基本操作之一:查找为例来分析,如何实现有效的查找?

查找

实质:根据某个给定的关键词K,从集合R中找出与关键词K相同的数据

1. 静态查找

  • 定义:集合中的数据是固定的。没有插入和删除,对数据集的操作只有查找。——比如一本出版字典
  • 实现:一般使用数组存放数据
  • 方法:顺序查找

2. 动态查找

  • 定义:集合中数据是动态变化的。对数据集的操作有查找、插入和删除。——比如一个论文数据库

顺序查找详解:(实际上就是遍历)时间复杂度:O(n)

typedef struct LNode *List;
struct LNode{
    ElementType Element[MaxSize];
    int length;
};

int SequentialSearch(List Tbl,ElementType K)
{//遍历ElementType查找关键字为K的数据元素
    int i;
    Tbl->Element[0] = K;//建立哨兵,预先设立边界值而不需要每次都判断
    for(i = Tbl->Length; Tbl->Element[i] != K; i--);
    //查找成功返回下标,不成功返回0
    return i;
}

//不用哨兵的
int SequentialSearch(List Tbl,ElementType K)
{
    int i;
    //两个退循环条件,i控制边界,tbl检测是否相等
    for(i = Tbl->Length; i>0 && Tbl->Element[i] != K; i--);
    return i;
}

3.1.2 引子 二分查找例子(BinarySearch)

假设两个地点AB之间的高压电站有100w个,从A向B输电,某一天两个地方都突然停电了,现在需要排查是哪里的电站出问题。如果一个一个排查过去,平均需要50w次才能排查结束。如果先从最中央的一个电站开始排查,再向断电的那一半的中间...每次折半查找,那么只需要log2(1000000)=20次就可以排查完毕。

二分查找

  • 前提:数据元素的关键字需要是有序且连续存放
  • 退出条件:1.初始时right>left,结束时left>right,二者错位,说明查找失败2.查找成功,返回

3.1.3 引子 二分查找实现

二分查找代码

//函数参数表为存放着数据的列表Tbl和要找的元素K
int BinarySearch(List Tbl, ElementType K)
{
    //定义左中右标识变量,赋初值,-1为方便返回NoFound
    int left,right,mid,NoFound = -1;

    //初始左右边界,先让左边界为最左侧元素,右边界为表尾
    left = 1;
    right = Tbl->length;

    while(left <= right)
    {
        mid = (left + right)/2;
        //若中值大于要找的元素K
        if(K < Tbl->Element[mid]){
           right = mid - 1;//说明应该往左半侧找,把右边界更新为此时的中值-1即可
        }else if(K > Tbl->Element[mid]){
            left = mid + 1;
        }else{
            return mid;
        }
    }
    //如果找到了会提前退出循环,没找到会返回NoFound即-1
    return NoFound;
}

这个算法的时间复杂度是对数级的O(logN)

二分查找的启示

由二分查找判断元素的顺序可以绘制出如下判定树

从图中可以发现:

  • 每个结点需要查找的次数刚好等于这个结点所在的层数
  • 查找次数的上限是这个判定树的深度
  • 如果有n个结点,那么判定树的深度为[log2(N)]+1
  • 平均查找次数ASL = (每层个数*层数之和)/总结点数。此树ASL = (1+2*2+4*3+4*4)/11=3

那么如果直接将数据存储成树这样的形式,会不会对数据的查找更有裨益呢?当然会。之后我们就将讲到查找树这种存储形式。

3.1.4 树的定义

树(Tree):n(n>=0)个结点构成的有限集合

空树:n=0,即没有结点。其对应的是非空树。

对于任意一颗非空树,它具备以下性质:

树中有一个称为根(Root)的特殊结点,用r表示

其余结点可分为m(m>0)个互不相交的有限集T1、T2、...、Tm,其中每个集合本身也是一棵树,称为原来树的子树(SubTree)

非树:

  • 子树之间有相交

树:——  一种保证结点联通方式最小的连接方式

  • 子树之间不能相交
  • 除根结点以外,每个结点有且仅有一个父结点
  • 一颗N个结点的树有N-1条边

一些基本术语:

  1. 结点的度:结点子树个数(有几个直接相连的子结点)
  2. 树的度:树的所有结点中最大的度数(树所有结点里子树最多的那一项,子树的个数)
  3. 叶结点(Leaf):度为0的结点
  4. 父结点(Parent):有子树的结点是其子树的根节点的父结点
  5. 子结点(Child):也称孩子节点。若A结点是B结点的父结点,则称B结点是A结点的子结点。
  6. 兄弟结点(Sibiling):具有同一父结点的各结点彼此是兄弟结点
  7. 路径和路径长度:从结点n1到nk的路径为一个结点序列n1,n2,...,nk,ni是ni+1的父结点。路径所包含边的个数为路径的长度。
  8. 祖先结点(Ancestor):沿树根到某一结点路径上所有结点都是这个结点的祖先结点。(层数高的是层数低的祖先)
  9. 子孙结点(Descendant):某一结点的子树中的所有结点是这个结点的子孙
  10. 结点的层次(Level):规定根结点在一层,其它任一结点的层数是其父结点层数+1
  11. 树的深度(Depth):树中所有结点中的最大层次是这棵树的深度

3.1.5 树的表示

知道了树的抽象结构和基本概念,下面我们需要能在计算机中表示树这种结构。首先我们肯定是需要在已有的结构中选择一种。

 使用结构+链表

看似结构很像,实则在实现过程中,每个结点指向其他结点的个数并不相同,结构不一定能囊括所有情况。那如果将所有的结点都设计成一个形式,比如都留3个指针域,有的结点可能只用一个,但这样能保证结点结构统一,处理方便。但当树的体积非常庞大时候,这样的做法会造成巨大的浪费。

有一种较好的表示方法,同样是使用结构+链表的形式,所有结点结构相同。每个结点包含两个指针域,一个是FirstChild,指向这个结点的第一个孩子结点,另一个是NextSibiling,指向它的下一个兄弟结点。这种形式的树我们称为:二叉树(链表)

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习Se-net和Sk-net 附网络简单代码(pytorch)

&#xff08;一&#xff09;Se-net的原理和思路     Se-net严格来说是一个小结构&#xff0c;它可以直接插入已有的网络结构中&#xff0c;帮助原有结构获得更好的效果&#xff0c;如插入Resnet网络中。 Se-net的整个流程如下&#xff1a;     &#xff08;1&#xf…

chatgpt赋能Python-opencv_python打开摄像头

OpenCV Python打开摄像头&#xff1a;一种简单的图像处理方式 OpenCV是一种常用的图像处理库&#xff0c;可以用Python编程轻松进行图像和视频处理。其中&#xff0c;打开摄像头也是OpenCV中常用的一种方法。在这篇文章中&#xff0c;我们将介绍OpenCV Python打开摄像头的原理…

chatgpt赋能Python-numpy开根

NumPy开根 在科学计算中&#xff0c;开根运算是一个经常需要进行的操作&#xff0c;它非常有用&#xff0c;可以用来求解方程、计算距离或者简单地将数据压缩成更容易理解的形式等。NumPy是一个强大的库&#xff0c;被广泛地用于Python编程中&#xff0c;它提供了用于开根的特…

chatgpt赋能Python-mofan_python

Mofan Python&#xff1a;一个优秀的入门编程网站 介绍 Mofan Python 是一个致力于帮助人们快速入门 Python 编程的网站。该网站提供了各种编程资源&#xff0c;包括 Python 相关的教程、实例、项目&#xff0c;以及机器学习和深度学习课程等。它的特点在于提供了详细的代码解…

华为OD机试真题 Java 实现【投篮大赛】【2023Q1 100分】

一、题目描述 你现在是一场采用特殊赛制投篮大赛的记录员。 这场比赛由若于回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分&#xff0c;比赛开始时&#xff0c;记录是空白的。 你会得到一个记录操作的字符串列表 ops&#xff0c;其中 ops[i] 是你需要记录…

FastDDS安全机制1 - 安全配置

背景 OMG组织对于DDS的安全机制有着对应的定义&#xff0c;其定义在DDS-SECURITY文档中。 这其中主要包含了对应的身份认证、访问控制、通信加密和审计相关的插件。 资料来源&#xff1a;DDS-SECURITY 其实也主要保护了通信过程中的相关安全风险。 资料来源&#xff1a;DDS-S…

轻松保护文档安全:三种实用的PDF加密方法

在我们的日常工作中&#xff0c;经常会使用到PDF格式的文件。为了保护版权和隐私&#xff0c;有时候我们需要对文档进行加密处理。那么&#xff0c;如何对PDF进行加密呢&#xff1f;今天我将为大家介绍几种方法&#xff0c;其中包括记灵在线工具、迅捷PDF编辑器和Speedpdf。 方…

Debian11之 RKE2 部署 K8S 集群

官方地址 资源列表 主机IP主机名称主机角色软件192.168.111.50server1主节点1API Server、controller-manager 和 scheduler192.168.111.51server2主节点2API Server、controller-manager 和 scheduler192.168.111.52server3主节点3API Server、controller-manager 和 schedu…

SocketTools crack所有安全连接的默认安全协议

SocketTools crack所有安全连接的默认安全协议 在所有HTTP客户端组件中添加了对HTTP/2.0协议的支持。 更新了TLS 1.2(及更高版本)和SSH 2.0的安全选项&#xff0c;以使用Microsoft Windows 11和Windows Server 2022中提供的密码套件。较旧、安全性较低的密码套件已被弃用&#…

JavaScript 基础 DOM (二)

事件流 事件流是对事件执行过程的描述 事件捕获 从DOM的根元素开始去执行对应的事件 (从外到里) 事件冒泡 当一个元素的事件被触发时&#xff0c;同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒 泡 addEventListener 第3个参数决定了事件是在捕获阶…

(数据结构)栈的实现——再一次保姆级教学

目录 1. 栈 ​编辑 1.2 栈的实现 2. 代码的实现 2.1 初始化栈和销毁栈 2.2栈顶元素的插入 2.3栈顶元素的删除 栈元素删除 2.4栈顶元素的获取和栈元素的个数 1. 栈 1.1 栈的概念和结构 栈(Stack)是一种线性存储结构&#xff0c;它具有如下特点&#xff1a; &#xff0…

git的学习3

文章目录 一、git status 命令二、git diff 命令三、git commit 命令四、git reset 命令五、git rm 命令六、git mv 命令七、提交日志1、Git 查看提交历史2、git blame 总结 提交与修改部分 一、git status 命令 git status 命令用于查看在你上次提交之后是否有对文件进行再次…

jenkins集成sonarqube进行代码质量检测

Jenkins集成Sonar Qube实现代码扫描需要先下载整合插件 安装SonarQube scanner 插件&#xff0c;安装完后&#xff0c;插件展示如下 配置SonarQube 的配置信息 这里给名称取为&#xff1a;sonarqubeFirst&#xff0c; server Url设置为SonarQube的地址&#xff0c;为http:19…

类和对象【1】初识

全文目录 引言&#xff08;初识面向对象&#xff09;类和对象定义类访问限定及封装类定义的两种方式 类实例化与类对象大小this指针 总结 引言&#xff08;初识面向对象&#xff09; C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通…

如何使用Understand软件查看STM32单片机HAL库函数调用关系

在使用STM32单片机的HAL库函数编程时&#xff0c;会发现好多中断函数里面都有各种回调函数&#xff0c;还有好多函数的调用深度比较深&#xff0c;在编写代码的时候&#xff0c;有时候想查看某个函数是如何被调用的&#xff0c;查看起来非常麻烦。这时候就可以使用Understand软…

Android活动生命周期

GitHub&#xff1a;https://github.com/MADMAX110/Stopwatch 活动的生命不只是有创建和撤销&#xff0c;onCreate和onDestroy方法用来处理整个生命周期&#xff0c;除了这两个方法&#xff0c;另外还有一些处理活动可见性的生命周期方法。 具体来讲&#xff0c;有三个关键的生…

Flink学习——DataStream API

一个flink程序&#xff0c;其实就是对DataStream的各种转换。具体可以分成以下几个部分&#xff1a; 获取执行环境&#xff08;Execution Environment&#xff09;读取数据源&#xff08;Source&#xff09;定义基于数据的转换操作&#xff08;Transformations&#xff09;定义…

.net6 接收json数据 Controller http post

.net6 接收json数据 Controller http post 要添加这两个包 前端ajax请求 function tst() {$.ajax({type: "POST",contentType: "application/json",url: "/HelloWorld/Welcome",data: JSON.stringify({ "ID":1,"name": &…

Qt实现undo和redo功能--连续后退

刚开始想做这个的时候&#xff0c;我专门去找了Qt官方的测试例子&#xff0c;运行起来点了点&#xff0c;代码翻了翻。然后照猫画虎般的写了个测试例子。 不明白&#xff0c;为什么每个例子旁边会有个命令的显示列表&#xff0c;还巨丑的那种&#xff0c;这如果要放在别的程序…

DJ6-4 文件存储空间的管理

目录 6.4.1 空闲表 1、存储空间的分配与回收 2、空闲表法的优缺点 6.4.2 空闲链表 1、空闲盘块链 2、空闲盘区链 6.4.3 位示图 1、位示图的表示 2、存储空间的分配 3、存储空间的回收 4、位示图法的优缺点 6.4.4 成组链接 1、空闲盘块的组织 plus 个人理解图…