树和二叉树
文章目录
目录
树的概念
上课的时候说必考一题树概念,但其实都蛮简单的
根:没有前驱的结点
儿子:结点的后继是该结点的儿子
父亲/父母:若s是p的儿子,则p是s 的父亲/父母
度:一个结点的儿子个数为该结点的度。
叶结点:没有儿子的结点称为叶结点。
分支结点:有儿子的结点。
兄弟:有相同父亲的结点。
子孙:根为r的树的所有结点都是r的子孙,除r之外的所有结点是r的真子孙。
祖先:从根r到结点p的路径上的所有结点都是p的祖先,其中除p之外是p的真祖先。
有序树:树中各结点的儿子是有序的。
层数:根结点层数为1,其它 结点的层数是其父结点的层数加1。
高度(深度):树中结点的最大层数。空树的高度为0。
树林(森林):n(n>=0)个互不相交的树的集合。
二叉树
二叉树的概念
二叉树的每个结点至多有2个子女,而且有 左、右之分。
二叉树的递归定义:二叉树由结点的有限 集合构成,这个有限集合或者为空,或者 由一个根结点以及两棵不相交的分别称作 这个根的左子树和右子树的二叉树组成
二叉树表示算术表达式:分支结点对应运算符, 叶结点对应操作数。
满二叉树:一棵深度为h且 有2h-1个结点的二叉树。(每 个结点的度为0或2,且度为 0的结点只出现在最后一层)
完全二叉树:深度为h且有n 个结点的二叉树,当且仅当 每个结点都与深度为h的满 二叉树中编号从1~n的结点 一一对应时,称之为完全二 叉树。
满二叉树一定是完全二叉树,但完全二叉树不一定是满二叉树。完全二叉树最后一个结点之上一定是满二叉树。
二叉树的性质
性质1: 任何一棵含有n(n>0)个结点的二叉树 恰有n-1条边。n个节点有n-1条边
性质2:深度为h的二叉树至多有个结点 (h>=0). 二叉树的第i层最多有
个结点。
性质3:设二叉树的结点数为n,深度为h, 则┎log2(n+1)┒≤h≤n。深度h大于等于┎┒小于等于结点数n
性质4:如果一棵有n个结点的完全二叉树的结点,按层次序编号(每层从左至右), 则对任意结点i(1≤i≤n):
(1)若2i>n,则结点i无左子女;否则,结点2i为 结点i的左子女。
(2)若2i+1>n,则结点i无右子女;否则,结点 2i+1为结点i的右子女。
(3)若i=1,则结点i为二叉树的根结点;若i>1, 则结点[i/2]为其父母结点
总的来说就是下图
性质5:如果一颗二叉树每个分支结点都两 个儿子(如Huffman树),设叶结点个数为 n,则分支结点的个数为n-1。证明:设分支结点的个数为x,则该二叉树有 2x条边(每个分支结点下两条边),结点总数为n+x(分支+叶)。因为二叉树的边数为其结点数减1,所以2x=n+x-1,所以 x=n-1。
性质6:设二叉树中叶结点个数为n0, 只有 一个儿子的分支结点个数为n1, 有两个儿子的分支结点个数为n2,边的数量为e。 则:
e=2*n2+n1 用结点类型算边数
e=n0+n1+n2-1 用结点数算边数
n2=n0-1
当三叉树四叉树时,也有对应的公式可以类推的那种
2*n3+n2=n0-1、3*n4+2*n3+n2=n0-1....
二叉树的存储方式
顺序存储
会造成空间的浪费
链接存储
二指针式每个结点两个指针分别指向左儿子和右儿子。
三指针式每个结点比二指针多一个指向父亲的指针
树(树林)与二叉树的相互转换
总结一下就是
树->二叉树:我的右边的兄弟会变成我的右儿子,我的大儿子永远是我的好大儿
二叉树->树:我的大儿子永远是我的好大儿,我的右儿子会变成我的兄弟
其实和树转二叉树一样,原理就是根永远不会有右儿子,因为他没有兄弟 !
二叉树转树林就是把右儿子拎出来,右儿子的右儿子拎出.....
二叉树的遍历
四种遍历方式: 前序遍历、中序遍历、后序遍历、层序遍历
前序、中序、后序就是访问根节点的时机。层次序就是按顺序访问。
树的遍历
先根、后根、层序
基本和二叉树一样
先根: 1 2 4 6 5 7 8 12 3 9 10 11
后根: 4 5 7 6 8 2 12 10 9 11 3 1
树林的遍历
先根、后根
由遍历结果还原出二叉树
中序和任意都能还原出二叉树
线索化二叉树
n+1个空链域=总链域数(每个结点都可以有两条边)-(结点数-根结点)=2n-n+1
tag标志指针的状态,是指向线索还是树结构信息
对于线索
如果你是左儿子,那么你的左指针指向爷爷(如果有的话),右指针指向父亲
如果你是右儿子,那么你的右指针指向爷爷(如果有的话),左指针指向父亲
插入结点
意思是让q排在p后边
还是需要理解一下
非递归的遍历算法![](https://img-blog.csdnimg.cn/6022805977014966b80d97bada95bef8.png)
在访问完某结点后,不能立即放弃它,因 为遍历完它的左子树后,要从它的右儿子起遍历,所以在访问完某结点后,应保存它的指针,以便以后能从它找到它的右儿子。由于较先访问到的结点较后才重新利用,故应将访问到的结点按栈的方式保存