C#数据结构与算法揭秘七

简介:

前面介绍了线性结构,线性结构中的数据元素是一对一的关系。本章和下一章介绍两种非常重要的非线性结构:树形结构和图状结构。树形结构是一对多的非线性结构,非常类似于自然界中的树,数据元素之间既有分支关系,又有层次关系。树形结构在现实世界中广泛存在,如家族的家谱(图一)、一个单位的行政机构组织(图二)等都可以用树形结构来形象地表示。

树形结构在计算机领域中也有着非常广泛的应用,如 Windows 操作系统中对磁盘文件的管理、编译程序中对源程序的语法结构的表示等都采用树形结构。在数据库系统中,树形结构也是数据的重要组织形式之一。树形结构多叉树和二叉树两种,多叉树的操作实现比较复杂,但多叉树可以转换为二叉树进行处理,所以,本章主要讨论二叉树。

windows资源管理器是一个最典型的树形结构。

一张自然中典型的二叉树。

第一个问题,什么是树。所谓的树(Tree)是 n(n≥0)个相同类型的数据元素的有限集合。树中的数据元素叫结点(Node)。n=0 的树称为空树(Empty Tree);对于 n>0 的任意非空树 T 有: 

(1)有且仅有一个特殊的结点称为树的根(Root)结点,根没有前驱结点; 如图所示。

(2)若n>1,则除根结点外,其余结点被分成了m(m>0)个互不相交的集合T1,T2,…,Tm,其中每一个集合Ti(1≤i≤m)本身又是一棵树。树T1,T2,…,Tm
称为这棵树的子树(Subtree)。如图所示:


由树的定义可知,树的定义是递归的,用树来定义树。因此,二叉树的许多算法都使用了递归。 树的形式定义为:树(Tree)简记为 T,是一个二元组, T = (D, R) 其中:D 是结点的有限集合;  是结点之间关系的有限集合。

由上述两个特点可知,图 5.2所示的都不是树

树的术语很多,我们来一一进行介绍。

1、结点(Node):表示树中的数据元素,由数据项和数据元素之间的关系组成。在下图中,共有 7个结点。
2、结点的度(Degree of Node):结点所拥有的子树的个数,在下图中,孙子结点的度为 3。
3、树的度(Degree of Tree):树中各结点度的最大值。在下图中,树的度为3.
4、叶子结点(Leaf Node):度为 0 的结点,也叫终端结点。在下图中,子结点和孙子结点都是叶子结点。
5、 分支结点(Branch Node): 度不为 0 的结点, 也叫非终端结点或内部结点。在下图中,根结点和子结点是分支结点。

6、孩子(Child):结点子树的根。在下图中,子结点是根结点的孩子。 

7、双亲(Parent):结点的上层结点叫该结点的双亲。在下图中,子结点的双亲是根结点。
8、祖先(Ancestor):从根到该结点所经分支上的所有结点。在下图中,孙子结点的祖先是子节点和根节点。
9、子孙(Descendant):以某结点为根的子树中的任一结点。在下图中,除根结点之外的所有结点都是根结点的子孙。
10、兄弟(Brother):同一双亲的孩子。在下图中,子结点互为兄弟。
11、结点的层次(Level of Node):从根结点到树中某结点所经路径上的分支数称为该结点的层次。根结点的层次规定为 1,其余结点的层次等于其双亲结点的层次加 1。

12、堂兄弟(Sibling):同一层的双亲不同的结点。
13、树的深度(Depth of Tree):树中结点的最大层次数。在下图中,树的深度为 3。
14、无序树(Unordered Tree):树中任意一个结点的各孩子结点之间的次序构成无关紧要的树。通常树指无序树。
15、有序树(Ordered Tree):树中任意一个结点的各孩子结点有严格排列次序的树。二叉树是有序树,因为二叉树中每个孩子结点都确切定义为是该结点的左孩子结点还是右孩子结点。
16、森林(Forest):m(m≥0)棵树的集合。自然界中的树和森林的概念差别很大,但在数据结构中树和森林的概念差别很小。从定义可知,一棵树有根结点和m 个子树构成,若把树的根结点删除,则树变成了包含 m 棵树的森林。当然,根据定义,一棵树也可以称为森林

树的逻辑表示方法很多,这里只讲几种常见的表示方法。
1、直观表示法
它象日常生活中的树木一样。整个图就象一棵倒立的树,从根结点出发不断扩展,根结点在最上层,叶子结点在最下面,如上图所示。
2、凹入表示法
每个结点对应一个矩形,所有结点的矩形都右对齐,根结点用最长的矩形表示,同一层的结点的矩形长度相同,层次越高,矩形长度越短,上图中的树的凹入表示法如下图所示。

3、广义表表示法
用广义表的形式表示根结点排在最前面, 用一对圆括号把它的子树结点括起来,子树结点用逗号隔开。树的广义表表示如下: 

(根结点(子结点(孙子结点,孙子结点),子结点(孙子结点,孙子结点)))

4、嵌套表示法
类似数学中所说的文氏图表示法,如下图所示。

二叉树的形态共有 5 种:空二叉树、只有根结点的二叉树、右子树为空的二叉树、左子树为空的二叉树和左、右子树非空的二叉树。二叉树的 5 种形态如图所示。

(1) 满二叉树(Full Binary Tree): 如果一棵二叉树只有度为 0 的结点和度为 2的结点, 并且度为 0 的结点在同一层上, 则这棵二叉树为满二叉树, 如图(a)所示。
由定义可知,对于深度为k的满二叉树的结点个数为 2k-1。

(2)完全二叉树(Complete Binary Tree):深度为 k,有 n 个结点的二叉树当且仅当其每一个结点都与深度为 k,有 n 个结点的满二叉树中编号从 1 到 n的结点一一对应时,称为完全二叉树,如下图(b)所示。 完全二叉树的特点是叶子结点只可能出现在层次最大的两层上, 并且某个结点的左分支下子孙的最大层次与右分支下子孙的最大层次相等或大 1。

性质 1 一棵非空二叉树的第i层上最多有 2
i-1个结点(i≥1)。
证明:采用数学归纳法进行证明。当n=1时,二叉树只有 1层,这一层只有根结点一个结点,所以第 1 层的结点数为 21-1=1,结论成立。假设当n=N时结论成立,即第N层最多有 2N-1个结点;当n=N+1 时,根据二叉树的定义,第N层的每个结点最多有 2个子结点,所以第N+1层上最多有 2N-1*2=2N=2(N+1)-1个结点,
结论成立。综上所述,性质 1成立。


性质 2 若规定空树的深度为 0,则深度为k的二叉树最多有 2
k-1 个结点(k≥0)。
证明:当k=0时,空树的结点数为 20-1=0,结论成立。当深度为k(k>0)时,
由性质 1可知,第i(1≤i≤k)层最多有 2i-1个结点,所以二叉树的最多结点数是:1+2^1+.......+2^(i-1)=2^i-1


性质 3 具有n个结点的完全二叉树的深度k-为log2n+1。
证明:根据性质 2和完全二叉树的定义可知,当一棵完全二叉树的结点数为n、深度为 k 时,有 2k-1-1<n≤2k-1
即 2k-1≤n<2k对不等式取对数,有 k-1≤log2n<k 由于k是整数,所以有k=log2n+1。 

性质 4 对于一棵非空二叉树,如果度为 0 的结点数目为n0,度为 2 的结点数目为n2,则有n0= n2+1。
证明:设n为二叉树的结点总数,n1二叉树中度为 1的结点数目,则有 n= n0+ n1+ n2在二叉树中,除根结点外,其余结点都有唯一的一个进入分支。设 B 为二叉树中的分支总数,则有 B=n-1 这些分支由度为1和度为2的结点发出的, 一个度为1的结点发出一个分支,一个度为 2的结点发出 2个分支,所以有 B= n1+2 n2  综合上面 3个式子,可以得到 n0= n2+1 

性质 5 对于具有 n 个结点的完全二叉树,如果按照从上到下和从左到右的顺序对所有结点从 1 开始编号,则对于序号为 i 的结点,有:
(1) 如果 i>1, 则序号为 i 的结点的双亲结点的序号为 i/2( “/” 表示整除);如果 i=1,则该结点是根结点,无双亲结点。
(2)如果 2i≤n,则该结点的左孩子结点的序号为 2i;若 2i>n,则该结点无左孩子。
(3)如果 2i+1≤n,则该结点的右孩子结点的序号为 2i+1;若 2i+1>n,则该结点无右孩子

这就是对二叉树的性质的基本介绍,下届从源代码的层次来进行实现。

目录
相关文章
|
1月前
|
开发框架 算法 搜索推荐
C# .NET面试系列九:常见的算法
#### 1. 求质数 ```c# // 判断一个数是否为质数的方法 public static bool IsPrime(int number) { if (number < 2) { return false; } for (int i = 2; i <= Math.Sqrt(number); i++) { if (number % i == 0) { return false; } } return true; } class Progr
58 1
|
4月前
|
搜索推荐 算法 C#
【Unity 3D】C#中冒泡排序、选择排序、插入排序等算法的详解(附源码 超详细)
【Unity 3D】C#中冒泡排序、选择排序、插入排序等算法的详解(附源码 超详细)
47 1
|
4月前
|
机器学习/深度学习 算法 C#
C# | 凸包算法之Andrew‘s,获取围绕一组点的凸多边形的轮廓点
这篇关于凸包算法的文章,本文使用C#和Andrew’s算法来实现凸包算法。 首先消除两个最基本的问题: 什么是凸包呢? 凸包是一个包围一组点的凸多边形。凸多边形是指多边形中的每个内角都小于180度的多边形。 凸包算法有什么用呢? 凸包算法的作用是找到这个凸多边形,并且使用最少的点来绘制出它的轮廓。凸包算法在计算机图形学、计算几何和机器学习等领域中有着广泛的应用。
57 0
|
1月前
|
搜索推荐 C#
C#实现选择排序算法
C#实现选择排序算法
16 2
|
1月前
|
搜索推荐 C#
C#实现冒泡排序算法
C#实现冒泡排序算法
19 0
|
3月前
|
算法 C#
C# .Net Core bytes转换为GB/MB/KB 算法
C# .Net Core bytes转换为GB/MB/KB 算法
41 0
|
4月前
|
存储 算法 数据处理
C# | 上位机开发新手指南(十一)压缩算法
流式压缩 流式压缩是一种能够实时处理数据流的压缩方式,例如音频、视频等实时传输的数据。 通过流式压缩算法,我们可以边读取边压缩数据,并能够随时输出已压缩的数据,以确保数据的实时性和减少存储和传输所需的带宽。 块压缩 块压缩则是将数据划分为固定大小的块,在每个块内进行独立的压缩处理。块压缩通常适用于文件、存储、传输等离线数据处理场景。 字典压缩 字典压缩是一种基于字典的压缩算法,通过建立一个字典来存储一组重复出现的字符串,并将这些字符串替换成字典中相应的索引,从而减少数据的存储和传输。字典压缩算法可以更好地处理数据中的重复模式,因为它们可以通过建立字典来存储和恢复重复出现的字符串。
46 0
C# | 上位机开发新手指南(十一)压缩算法
|
4月前
|
算法 C# 数据安全/隐私保护
C# | 上位机开发新手指南(十)加密算法——ECC
本篇文章我们将继续探讨另一种非对称加密算法——ECC。 严格的说,其实ECC并不是一种非对称加密算法,它是一种基于椭圆曲线的加密算法,广泛用于数字签名和密钥协商。 与传统的非对称加密算法(例如RSA)不同,ECC算法使用椭圆曲线上的点乘法来生成密钥对和进行加密操作,而不是使用大数分解等数学算法。这使得ECC算法具有相同的安全性和强度,但使用更少的位数,因此在资源受限的环境中具有优势。 ECC算法虽然使用公钥和私钥进行加密和解密操作,但是这些操作是基于点乘法实现的,而不是基于大数分解等算法实现的。因此,ECC算法可以被视为一种非对称加密算法的变体,但是它与传统的非对称加密算法有所不同。
131 0
C# | 上位机开发新手指南(十)加密算法——ECC
|
4月前
|
XML 算法 安全
C# | 上位机开发新手指南(九)加密算法——RSA
RSA的特性 非对称性 RSA算法使用公钥和私钥两个不同的密钥,公钥用于加密数据,私钥用于解密数据。公钥可以公开,任何人都可以使用,而私钥只有密钥持有人可以访问。 安全性 RSA算法基于大数分解难题,即将一个大的合数分解成其质数因子的乘积。由于目前没有有效的算法可以在合理的时间内对大质数进行分解,因此RSA算法被认为是一种安全的加密算法。 可逆性 RSA算法既可以用于加密,也可以用于解密。加密和解密都是可逆的过程,只要使用正确的密钥,就可以还原原始数据。 签名 RSA算法可以用于数字签名,用于验证数据的完整性和真实性。签名过程是将数据使用私钥进行加密,验证过程是将签名使用公钥进行解密。
102 0
C# | 上位机开发新手指南(九)加密算法——RSA
|
4月前
|
算法 搜索推荐 安全
C# | 上位机开发新手指南(八)加密算法——AES
AES——这是在加密算法中相当重要的一种加密方式! 虽然这个世界上已经存在了非对称加密算法(比如RSA、ECC等),但是在对称加密算法中,AES的地位依然相当重要。与非对称加密算法不同,对称加密算法使用的是相同的密钥对数据进行加密和解密,因此其加密和解密速度更快,而且更加高效。而在对称加密算法中,AES是目前最安全、最可靠的加密算法之一,其加密强度和运行效率都非常高。因此,无论是在个人计算机、移动设备,还是在服务器和云计算等领域,AES都被广泛应用于数据的加密和解密过程中。
94 0
C# | 上位机开发新手指南(八)加密算法——AES