数据结构——树

一、基本概念

        树是一种非线性结构。树的严格的数学定义是:如果一组数据中除了第一个节点(第一个节点称为根节点,没有直接前驱节点)之外,其余任意节点有且仅有一个直接前驱节点,有 0 个或者多个直接后继节点,这样的一组数据形成一棵树。这种特性简称为一对多的逻辑关系。

二、常见例子

        日常生活中,很多数据都是树状逻辑结构。由于树状结构表现出来的都是具有层次的,因此也被称为层次结构的组织形式。比如一个公司中的职员层级关系、一个学校中的院系层级关系、淘汰赛中的各次比赛队伍、一个家族中的族谱成员关系等。

        通常,在逻辑上表达一棵抽象的树状结构时,习惯于将树根放在顶部,树枝树杈向下生长,如图:

对于一棵树来说,有如下基本术语:

(一) 根(root)(A):树的第一个节点,没有直接前驱节点。

(二) 双亲节点(parent):某节点的直接前驱节点,称为该节点的双亲节点,或者称为父节点。例如A 是 B 的父节点。

(三) 孩子节点(child):某节点的直接后继节点,称为该节点的孩子节点。例如 B、C、D 均为A的孩子节点。

(四) 节点的层次(level):根节点所在的层次规定为第1层,其孩子所在的层次为第2层,后代节点以此类推。例如节点 E 的层次是3。

(五) 节点的度(degree)(有几个孩子):一个节点拥有的孩子节点的总数,称为该节点的度。比如节点 B 的度为2。

(六) 叶子(leaf)(没有孩子的节点):一棵树中,度等于 0 的节点,被称为叶子,又称为终端节点。比如节点 K、L、F、G、M、I、J 均为叶子。

(七) 树的高度(height):一棵树中所有节点的层次的最大值,称为这棵树的高度,又称为树的深度。比如上面的树的高度为 4 。

(八) 有序树与无序树:一棵树中,如果某个节点的孩子节点之间是有次序的,则称这棵树为有序树,反之称为无序树。

三、二叉树

        在各种不同的树状结构中,最常见的、也是最重要的是二叉树(Binary Tree)二叉树的定义:1. 有序树;2. 任意节点的度 ≤ 2。

如图:

        其中 8 是根节点,14 是 10 的右孩子(因为二叉树是有序树,因此严格区分左右),而 13 则是 14 的左孩子。

        为了方便对二叉树进行操作,通常会对一棵树进行标号:从上到下,从左到右进行标号:

( 注意:没有孩子节点的地方也要标出来)

二叉树的特性:

二叉树的基本概念:

(一) 满二叉树 / 完美二叉树:(full / perfect binary tree) --- 儿孙满堂(家大业大):树的高度为 ,且树的节点总数达到 2的k次方−1 的二叉树。

(二) 完全二叉树:(complete binary tree):各节点的标号连续。

(三) 平衡二叉树:(balance binary tree):任意节点的两棵子树高度差 ≤ 1

(四) 退化二叉树:(degenerate binary tree)--- 三代单传(一脉相承):所有节点的度 ≤ 1,此时的二叉树实际上已经退化成链表。

四、存储形式

树可以使用顺序存储,也可以使用链式存储。

(一)顺序存储

        在顺序存储中,数据元素之间的逻辑关系是用物理位置来表达的,而二叉树中每一个节点都有一个对应的标号,因此可以使用标号来作为数组的下标,但是,除非是完美或者完全二叉树,否则会浪费存储空间。

        而节点彼此之间的关系,要用到二叉树标号的基本特性。观察二叉树的标号会发现规律:

        1. 根节点标号为 1,根节点没有父节点;

        2. 根节点标号为 n,其父节点的标号为 n/2 ;

        3. 标号为 n 的节点,其左孩子(若有)的标号为 2n ,其右孩子(若有)的标号为 2n+1。

        根据以上规律,在顺序存储的二叉树中,虽然没有任何信息连接节点 e 和 f,但根据他们的下标序号,可以得知 e 是 f 的父节点,且 f 是 e 的左孩子。

(二)链式存储

        二叉树的链式存储与链表类似,使用指针来直接将节点的逻辑关系串起来,如图:

五、树的遍历

        遍历,就是按某种规律访问每一个节点。对于线性表来说,遍历算法就是从头跑到尾,因为线性表是 1 对 1 的关系。但是树状结构是非线性的,因此从根节点开始遍历所有节点可以有多种不同的算法:

        1. 前序遍历:根节点 - 左子树 - 右子树(、左、右)

        2. 中序遍历:左子树 - 根节点 - 右子树(左、、右)

        3. 后序遍历:左子树 - 右子树 - 根节点(左、右、

        4. 按层遍历:从上到下,从左到右依次访问节点

        注意:前中后序遍历,都是递归算法。以前序遍历为例,当访问完根节点,进而要访问左子树时,由于左子树本身一棵二叉树,因此也需要进行前序遍历,也是先访问左子树的根节点,然后再依次访问左子树的左子树和左子树的右子树。如图:

技巧:知道每个节点的身份,看其优先级来执行

(一) 前序遍历的序列是:F - [BADCE] - [GIH]

        其中,对于根节点 F 来说,BADCE是左子树,GIH是右子树。

        对左子树的访问,也符合前序遍历的定义,即:B - [A] - [DCE]。

(二) 中序遍历的序列是:[ABCDE] - F - [GHI]

(三) 后序遍历的序列是:[ACEDB] - [HIG] - F

(四) 按层遍历就按照字面意思理解即可,序列是:F - BG - ADI - CEH

(我感觉第一步就是,要分清楚哪个是根节点(因为根节点只有 1 个)、哪部分是左子树、哪部分是右子树;第二步就是,看清楚是怎样的遍历形式,第三步就是,根据遍历的形式,判断好左子树、右子树的遍历顺序)

以上内容就是我的课后笔记了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值