数据结构——树

树的基础知识
树的定义
树是N(N≥0)个结点的有限集合,N=0时,称为空树。

任意一棵空树满足如下条件:
1)有且仅有一个特定的称为根的结点。

2)当N>1时,其余结点可分为m(m>0)个互不相交的有限集合T1,T2,…,Tm,其中每一个集合本身又是一棵树,并且称为根节点的子树。

树是一种递归的数据结构。树作为一种逻辑结构,同时也是一种分层结构,具有以下结构:

1)树的根节点没有前驱节点,除根节点之外的所有节点有且只有一个前驱节点。

2)树中所有节点可以有零个或多个后继节点。

树适合于表示有层次结构的数据。

结点的深度:是从根结点开始自顶向下逐层累加的。

结点的高度:是从叶结点开始自底向上逐层累加的。

树的高度:是树中结点的最大层数。

树的性质
1)树中的结点树等于所有结点的度数加1;

2)度为m的树中第i层上至多有mi-1个结点(i≥1);

3)高度为h的m叉树至多有(mh-1)/(m-1)个结点;

4)具有n个结点的m叉树的最小高度为logm(n(m-1)+1);

二叉树的相关概念
二叉树的定义
二叉树是另一种树形结构,其特点是每个结点至多只有两棵子树,并且,二叉树的子树有左右之分,其次序不能任意颠倒。

二叉树是n(n≥0)个结点的有限集合:
1)或者为空二叉树,即n=0;

2)或者由一棵根结点和两个互不相交的被称为根的左子树和右子树组成。左右子树又分别是一棵二叉树。

二叉树与度为2的有序树的区别:
1)度为2的树至少有3个结点,而二叉树可以为空;

2)度为2的有序树的孩子结点的左右次序是相对于另一个孩子结点而言的,如果某个结点只有一个孩子结点,这个孩子结点就无须区分其左右次序,而二叉树无论是孩子数是否为2,均需确定其左右次序,也就是说二叉树的结点次序不是相对于另一个结点而言,而是确定的。

满二叉树
一棵高度为h,并且含有2h-1个结点的二叉树称为满二叉树。

完全二叉树
设一个高度为h,有n个结点的二叉树,当且仅当其每一个结点都与高度为h的满二叉树中编号为1~n的结点一一对应时,称为完全二叉树。该树特点如下:

1)若i≤n/2,则结点i为分支结点,否则为叶子结点。

2)叶子结点只可能在层次最大的两层上出现。对于最大层次中的叶子结点,都一次排序在该层最左边的位置上。

3)如果有度为1的结点,只可能有一个,且该结点只有左孩子而无右孩子。

4)按层序编号后,一旦出现某结点(其编号为i)为叶子结点或只有左孩子,则编号大于i的结点均为叶子结点。

5)若n为奇数,则每个分支结点都有左子女和右子女;若n为偶数,则编号最大的分支结点(编号为n/2)只有左子女,没有右子女,其余分支结点左、右子女都有。

二叉排序树
一棵二叉树或者是空二叉树,或是具有如下性质的二叉树:左子树上所有结点的关键字均小于根结点的关键字;右子树的所有结点的关键字均大于根结点的关键字。左右子树又各是一棵二叉排序树。

平衡二叉树
树上任一结点的左子树和右子树的深度之差不超过1.

二叉树性质
1)非空二叉树上叶子结点数等于度为2的结点数加1,即N0=N2+1;

2)非空二叉树上第K层上至多有2k-1个结点;

3)高度为H的二叉树至多有2H-1个结点;

4)对完全二叉树按从上到下、从左到右的顺序依次编号1,2,…,N,则有以下关系:

当i>1时,结点i的双亲结点编号为i/2,即当i为偶数时,其双亲结点的编号为i/2,它是双亲结点的左孩子;当i为奇数时,其双亲结点的编号为(i-1)/2,它是双亲结点的右孩子。

当2i≤N时,结点i的左孩子编号为2i,否则无左孩子;

当2i+1≤N时,结点i的右孩子编号为2i+1,否则无右孩子;

结点i所在层次为log2i+1;

5)具有N个结点的完全二叉树的高度为log2(N+1);

二叉树的存储结构
1、顺序存储结构

二叉树的顺序存储结构就是用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树上的结点元素,即将完全二叉树上编号为i的结点元素存储在某个数组下标为i-1的分量中,然后通过一些方法确定结点在逻辑上的父子和兄弟关系。

完全二叉树和满二叉树采用顺序存储比较合适,树中结点的序号可以唯一地反映出结点之间的逻辑关系,这样既能最大可能地节省存储空间,又可以利用数组元素的下标值确定结点在二叉树中的位置,以及结点之间的关系。

2、链式存储结构

顺序存储对空间利用率较低,因此一般的二叉树都采用链式存储结构。

在二叉树中,结点结构通常包括若干数据域及若干个指针域。二叉链表至少包含3个域:数据域data、左指针域lchild和右指针域rchild。

在含有n个结点的二叉链表中含有n+1个空链域。

二叉树的遍历
1、先序遍历

2、中序遍历

3、后序遍历

4、递归算法和非递归算法的转换

可以借助栈。将二叉树的递归遍历算法转换为非递归算法,以中序遍历为例,先扫描(并非访问)根节点的所有左节点并将它们一一进栈。然后出栈一个节点p,则访问它。然后扫描该节点的右孩子结点,将其进栈,再扫描该右孩子结点的所有左节点并一一进栈,如此继续,直到栈空为止。

5、层次遍历

借助一个队列。先将二叉树根节点入队,然后出队,访问该节点,如果他有左子树,则将左子树根节点入队;如果它有右子树,则将右子树根节点入队。然后出队,对出队节点访问,如此反复,直到队列为空。

6、由遍历序列构造二叉树

由二叉树的先序序列和中序序列可以唯一的确定一棵二叉树,在先序遍历序列中,第一个节点一定是二叉树的根节点,而在中序遍历中,根节点必然将中序序列分歌成两个子序列,前一个子序列就是根节点的左子树的中序序列,后一个子序列是根节点的右子树的中序序列。根据这两个子序列,在先序序列中找到对应的左子序列和右子序列。在先序序列中,左子序列的第一个节点是左子树的根节点,右子序列的第一个节点是右子树的根节点。如此递归下去即可。

同理,由二叉树的后序序列和中序序列也可以唯一的确定一棵二叉树。

由二叉树的层序序列和中序序列也可以唯一的确定一棵二叉树。

树的存储结构
1、双亲表示法

该存储方式采用一组连续空间来存储每个节点,同时在每个节点中增设一个伪指针,指示其双亲结点在数组中的位置。

该存储结构利用了每个节点只有唯一双亲的性质,可以很快得到每个节点的双亲结点,但是求节点的孩子时需要遍历整个结构。

2、孩子表示法

将每个节点的孩子结点都用单链表链接起来形成一个线性结构,则N个节点就有N个孩子链表。

对于这种存储方式寻找子女的操作非常直接,而寻找双亲的操作需要遍历N个节点中孩子链表指针域所指向的N个孩子链表。

3、孩子兄弟表示法

又称为二叉树表示法。即以二叉链表作为树的存储结构。孩子兄弟表示法是使每个节点包括三部分内容:节点值、指向节点第一个孩子结点的指针和指向节点下一个兄弟节点的指针。

这种存储表示法比较灵活。最大的优点是可以方便的实现树转换为二叉树的操作,易于查找节点的孩子等。缺点是从当前节点查找其双亲结点比较麻烦。

树、森林和二叉树的转换
树转换为二叉树:

每个节点左指针指向它的第一个孩子结点,右指针指向它在树中的相邻兄弟节点,表示为“左孩子右兄弟”。由于根节点没有兄弟,所以,树转换得到的二叉树没有右子树。

森林转换为二叉树:

先将森林中的每一棵树转换成二叉树,再将第一棵树的根作为转换后的二叉树的根,第一棵树的左子树作为转换后二叉树根的左子树,第二棵树作为转换后二叉树的右子树,第三棵树作为转换后二叉树根的右子树的右子树,以此类推,就可以将森林转换为二叉树。

二叉树转换为森林:

若二叉树非空,则二叉树根及其左子树为第一棵树的二叉树形式,二叉树根的右子树又可以看做是一个由除第一棵树外的森林转换后的二叉树,应用同样的方法,直到最后产生一棵没有右子树的二叉树为止,二叉树转换为树或森林是唯一的。

树和二叉树的应用
1、二叉排序树(BST)

二叉排序树或者是一棵空树,或是一棵具有下列特性的非空二叉树:

1)若左子树非空,则左子树上所有结点关键字值均小于根结点的关键字值。

2)若右子树非空,则右子树上所有结点关键字值均大于根结点的关键字值。

3)左、右子树本身也是一棵二叉排序树。

二叉排序树的查找:

二叉排序树的查找是从根节点开始,沿某一分支逐层向下进行比较的过程。若二叉排序树非空,将给定值与根节点的关键字比较,若相等,则查找成功;若不等,则当根节点的关键字大于给定关键字值时,在根节点的左子树中查找,否则在根节点的右子树中查找。

二叉排序树的删除:

1)如果被删除节点z是叶节点,则直接删除,不会破坏二叉排序树的性质。

2)若节点z只有一颗左子树或右子树,则让z的子树成为z父节点的子树,替代z的位置。

3)若节点z有左、右两棵子树,则令z的直接后继(或直接前驱)替代z,然后从二叉排序树中删去这个直接后继(或直接前驱),这样就转换成了第一或第二种情况。

二叉排序树的查找效率:

二叉排序树查找算法的平均查找长度,主要取决于树的高度。

就维护表的有序性而言,二叉排序树无须移动节点,只需修改指针即可完成插入和删除操作,平均执行时间为O(log2n).二分查找的对象是有序顺序表,若有插入和删除节点的操作,所花的代价是O(n)。当有序表是静态查找表时,宜用顺序表作为其存储结构,而采用二分查找实现其查找操作;若有序表是动态查找表,则应选择二叉排序树作为其逻辑结构。

2、平衡二叉树(AVL)

在插入和删除二叉树节点树,要保证任意节点的左、右子树高度差的绝对值不超过1,这样的二叉树称为平衡二叉树。

定义节点左子树与右子树的高度差为该节点的平衡因子。(-1、1、0)

平衡二叉树的插入:

1)LL平衡旋转(右单旋转)

	向节点A的左孩子的左子树上插入新节点

2)RR平衡旋转(左单旋转)

	向节点A的右孩子的右子树上插入新节点

3)LR平衡旋转(先左后右双旋转)

	向节点A的左孩子的右子树上插入新节点

4)RL平衡旋转(先右后左双旋转)

	向节点A的右孩子的左子树上插入新节点

平衡二叉树的查找:

平衡二叉树上进行查找的过程和二叉排序树相同。

3、哈夫曼(Huffman)树和哈弗曼编码

树中节点被赋予一个表示某种意义的数值,称为该节点的权。

根节点到任意节点的路径长度(经过的边数)与该节点上权值的乘积称为该节点的带权路径长度。

树中所有叶节点的带权路径长度之和称为该树的带权路径长度,记为WPL。

在含有N个带权叶子节点的二叉树中,其中带权路径长度最小的二叉树称为哈夫曼树,也称为最优二叉树。

哈夫曼树的构造:

1)将N个节点分别作为N棵仅含一个节点的二叉树,构成森林F。

2)构造一个新节点,并从F中选取两棵根节点权值最小的树作为新节点的左、右子树,并且将新节点的权值置为左、右子树上根节点的权值之和。

3)从F中删除刚才选出的两棵树,同时将新得到的树加入F中。

4)重复2)、3),直至F中只剩下一棵树为止。

哈夫曼树特点:

1)每个初始节点最终都成为叶节点,并且权值越小的节点到根节点的路径长度越大。

2)构造过程中共新建了N-1个节点(双分支结点),因此哈夫曼树中节点总数为2N-1.

3)每次构造都选择2棵树作为新节点的孩子,因此哈夫曼树中不存在度为1的节点。

哈夫曼编码:

从根至该字符的路径上边标记的序列,左子树为0,右子树为1;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值