数据结构基础知识核心归纳(三)

来源:互联网 发布:大数据有限公司 编辑:程序博客网 时间:2024/05/16 11:40
数据结构基础知识核心归纳(三)
转载请声明出处:http://blog.csdn.net/andrexpert/article/details/77907894

     

Android                                          Java                                            数据结构
Android基础技术核心归纳(一)     Java基础技术核心归纳(一)     数据结构基础知识核心归纳(一) 
Android基础技术核心归纳(二)     Java基础技术核心归纳(二)     数据结构基础知识核心归纳(二)  
Android基础技术核心归纳(三)     Java基础技术核心归纳(三)    数据结构基础知识核心归纳(三)  
Android基础技术核心归纳(四)     Java基础技术核心归纳(四)


     不知不觉又是一年的9月,今天跟一个师弟聊天,谈到了他现在面试的一些情况,突然想起自己当年也是这么走过来的,顿时感慨良多。Android/Java经验汇总系列文章,是当初自己毕业时笔试、面试和项目开发中相关的总结,虽然不是很高深的东西,也没有归纳得很全面,但是对Android、算法、Java把握个大概还是没问题,今天特意将这些文章放出来,希望能够对看到这个系列文章的毕业生朋友一点帮助吧。当然,由于受当时知识面的限制,归纳得可能不是很准确,若有疑问就留言吧,我就不细看了。


1.赫夫曼树与赫夫曼编码
1.赫夫曼树

(1)定义:假设有n个权值{w1,w2,...,wn},构造一棵有n个叶子结点的二叉树,每个叶子结点带权为wk,每个叶子的路径长度为lk,则其中树的带权路径长度WPL=∑(wk*lk)最小的二叉树称为赫夫曼树,也称最优二叉树。


   ,该树的带权路径长度WPL = ∑(wk*lk) = 1*10+2*70+3*15+3*5=210.
● 叶子的路径长度lk:从根结点到叶子结点之间的分支数目总和;
● 树的带权路径长度WPL:树中所有叶子结点的带权
2.构造赫夫曼树算法
(1)根据给定的n个权值{w1,w2,....,wn}构成n棵二叉树的集合F={T1,T2,...,Tn},其中每棵二叉树Tk中只有一个带权为wk根结点,其左右子树均为空;
(2)在F中选择两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为左右子树上根结点的权值之和;
(3)在F中删除这两棵树,同时将新得到的二叉树加入F中;
(4)重复2和3步骤,直到F只含一棵树为止,该树即为赫夫曼树。


注:左权值要小于右权值,先根据权值对结点进行排序,然后再取出最小的两个结点构成一个新的结点插入有序的位置。
3.赫夫曼编码
    赫夫曼编码是一种非常有用的数据压缩方法,通常能将数据压缩20%-90%.
(1)算法原理:假设需要编码的字符集为{d1,d2,...dn},各个字符在电文中出现的次数或频率集合为{w1,w2,...,wn},以d1,d2,...,dn作为叶子结点,以w1,w2,...,wn作为相应叶子结点的权值来构造一棵赫夫曼树。规定:赫夫曼树的左分支代表0,右分支代表1,则从根结点到叶子结点所经过的路径分支组成的0和1的序列便为该结点对应字符的编码,这就是赫夫曼编码。
(2)赫夫曼编码特点
    赫夫曼编码是一种无损压缩编码,赫夫曼编码的码长是变化的。对于出现频率高的信息,编码的长度较短;对于出现频率较低的信息,编码长度较长。
(3)举例
● 对字符串“BADCADFEED”,假设这6个字母出现的频率不同,A 27%,B %8,C 15%,D 15%,E 30%,F 5%,实现哈夫曼编码?
    解析:首先,得到一棵哈夫曼树;
                其次,将结点的左右权值改为分别改为0、1;
                最后,将这6个字母用从根节点到叶子所经过路径的0或1来编码,得到的编码表如下:


将“BADCADFEED”再次编码得到“1001010010101001000111100”,共25个字符,与之前编码得到的30个字符相比大约节约了17%的存储和传输成本。

● 关于哈夫曼树说法正确的是?
A)一棵哈夫曼树总共有23个结点,该树共有12叶子结点; (N个叶子结点,2N-1个结点)
B)是一种前缀编码;(正确)
C)同一份数据对应的哈夫曼编码是唯一的;(错误,编码不是唯一的)
D)常用于数据压缩;(正确)
E)编码规则构成的树是一棵最优二叉树(正确,WPL最小的二叉树)
● 一个串字符仅由a、b、c、d、e五个字符组成,且各字符串出现的次数如下:a 16,b 44,c 5,d 19,e 12,对这个字符串进行赫夫曼编码,以下说法正确的是?
A)b应该被编为1位;(正确)
B)a和d应该被编为相同的位数;(错误,a的编码为"110",d为"10")
C)编码最长的是c,需要用5位表示;(错误,c的编码为"1110")
D)仅有一个字符被编位3位;(正确,b的编码为"0",e为"1111")
解析:关键在于构造一棵哈夫曼树,并对各终端结点进行"0"或"1"标记。

2.二叉树
1.二叉树

    二叉树(Binary tree)是n(n>=0)个结点的有限集合,该集合或者为空集,或者由一个根结点和两颗互不相交的,分别称为根结点的左子树和右子树的二叉树组成。其特点如下:
    ● 每个结点最多有两颗子树,不存在度大于2的结点;
    ● 需区分左右子树,且左右子树有序;
2.二叉树的建立(前序遍历)

3.二叉树的性质    
(1)在二叉树的第i层上至多有2^(i-1)个结点(i>=1);
(2)深度为k的二叉树至多有2^k-1个结点(k>=1); 其中,至多意味当为满二叉树时
(3)对任何一棵二叉树T,如果其终端结点数为no,度为2的结点数为n2,则no=n2+1;
(4)具有n个结点的完全二叉树的深度为[log2^n]+1([x]表示不大于x的最大整数);

解答:假设二叉树的结点总数为n,叶子结点为no,深度(高度)为k
      n=2^k-1--> n=1023
      n=2no-1 --> no=n+1)/2=512
3.遍历二叉树
1.二叉树的遍历

    是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。
2.二叉树遍历方法
(1)前序遍历
   规则:若二叉树为空,则返回为null。否则,先访问根结点,然后前序遍历左子树,再前序遍历右子树。C代码如下:

(2)中序遍历
    规则:若二叉树为空,则返回为null。否则,先中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。C代码如下:

(3)后序遍历
    规则:若二叉树为空,则返回为null。否则,从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。C代码如下: 

(4)层序遍历
    规则:若二叉树为空,则返回为null。否则,从树的第一层(即根结点)开发访问,从上而下逐层访问,在同一层,按从左到右的顺序对结点逐个访问。
举例:一个二叉树的先序遍历序列是:ADEGHBFC,中序遍历序列是:DGEABFHC,则后序遍历序列为:GEDFBCHA


4.堆
    堆是具有下列性质的完全二叉树:①每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;②每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。堆的数学描述如下:
    n个元素的序列{K1,K2,...,Kn}当满足Ki≤K2i且Ki≤K2i+1或者Ki≥K2i且Ki≥K2i+1,则称为堆。
★举例:对数列{46,79,56,38,40,84}建立大顶堆,则初始堆为_,最终排序结果__。 
第一步:首先对这些数据建立完全二叉树,填充的规则是按层次遍历将数据一一填入;
第二步:把二叉树调整为堆,即首先看第n/2个结点56,它比其子结点84小,所以应该把84和56的位置对调;

第三步:看第n/2-1个结点79,它比其他的两个子结点都要大,所以不用调整;接着看第n/2-2个结点46,它比它的两个子结点都小,所有把它和较大的子结点84对调;

第四步:接着我们看经过调整的结点46在当前的位置是否符合堆的规则,由于它小于其子结点56,所有要与子结点56进行交换,最终得到初始堆序列:84,79,56,38,40,46

注:对于结点i,i≥n/2时,表示结点i为叶子结点。
(2)根据初始堆获取最终排序
第一步:将根结点84与最后一个叶子结点46交换,然后,删除指向结点84的指针,调整完全二叉树中的结点重建新的大顶堆。结果:取出84;
            
第二步:再次将根结点79与最后一个叶子结点40交换,然后,删除指向结点79的指针,再次调整完全二叉树中的结点重建新的大顶堆。结果:取出79.;

依次类推,分别取出56、46、40、38。故最后的排序为:38、40、46、56、79、84
大堆---》增序   小堆---》减序
5.树
1.树

    树是n(n>=0)个结点的有限集,其中n=0时称为空树。在任意一颗非空树中:(1)有且仅有一个特定的称为根的结点;(2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1、T2、...、Tm,其中每一个集合本身又是一棵树,并且称为根的子树(Subtree)。结点拥有的子树称为结点的度,其中度为0的结点称为叶结点或终端结点;树内各结点的度的最大值称为树的度;树中结点的最大层次则称为树的深度。
                           
2.特殊二叉树
(1)斜树:所有的结点都只有左子树的二叉树称为左斜树;所有结点都是只有右子树的二叉树称为右斜树。特点:每一层都只有一个结点,结点的个数与二叉树的深度相同。
(2)满二叉树:在一颗二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
    满二叉树特点:a)所有的叶子只能出现在最下一层且处于同一层; 
                          b)非叶子结点的度一定是2;
                          c)在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。 
(3)完全二叉树:对一颗具有n个结点的二叉树按层序编号,如果编号为i(1=<i<=n)的结点与同样深度的满二叉树编号为i的结点在二叉树中位置完全相同,则这颗二叉树称为完全二叉树。
    完全二叉树特点:a)叶子结点只能出现在最下两层;
                              b)最下层的叶子一定出现在左部连续位置;
                              c)倒数二层,若有叶子结点,一定都在右部连续位置;
                              d)如果结点度为1,则该结点只有左孩子,即不存在只有右子树的情况;
                              e)同样结点数的二叉树,完全二叉树的深度最小。
(4)赫夫曼树:假设有n个权值{w1,w2,...,wn},构造一棵有n个叶子结点的二叉树,每个叶子结点带权为wk,每个叶子的路径长度为lk,则其中树的带权路径长度WPL=∑(wk*lk)最小的二叉树称为赫夫曼树,也称最优二叉树。 
(5)二叉排序树(用于查找算法)
    二叉排序树(Binary Sort Tree),又称为二叉查找树,具有下列性质的二叉树:
    ◆若它的左子树不空,则左子树上所有结点的值均小于它的根结构(双亲结点)的值;
    ◆若它的右子树不空,则右子树上所有结点的值均大于它的根结点(双亲结点)的值;
    ◆它的左、右子树也分别为二叉排序树。


(6)二叉平衡树
    为了提高二叉排序树的查找性能,我们希望二叉排序树是平衡的,即其深度与完全二叉树相同。二叉平衡树是一种①二叉排序树,其中每一个节点的左子树和右子树的②高度差(平衡因子)至多等于1,若平衡因子绝对值大于1则该二叉树就是不平衡的。
3.多路查找树   
(1)多路查找树
     ①每一个结点的孩子数可以多于两个,且②每一个结点处可以存储多个元素。由于它是查找树,所有元素之间存在某个特定的排序关系。引入多路查找树,就是为了打破每一个结点只能存储一个元素的限制。    
(2)B树(B-tree)
    是一种平衡的多路查找树,2-3树和2-3-4树都是B树的特例。结点最大的孩子数目称为B树的阶,所以2-3树是3阶B树,2-3-4树是4阶B树。一个m阶的B树具有如下属性: 
    ◆ 如果根结点不是叶结点,则其至少有两颗子树;
    ◆每一个非根的分支结点都有k-1个元素和k个孩子,其中[m/2]《k《m,每一个叶子结点n都有k-1个元素,其中[m/2]《k《m。
    ◆所有叶子结点都位于同一层次
    ◆所有分支结点包含下列信息数据(n,A0,K1,A1,K2,A2,.....,Kn,An),其中:Ki(i=1,2....,n)为关键字,且Ki<K(i+1)(i=1,2,...,n-1);Ai(i=0,2,...,n)为指向子树根结点的指针,且指针Ai-1所指子树中所有结点的关键字均小于Ki,An所指子树中所有结点的关键字均大于Kn.    
例如,对于数据集a[9]={7,1,2,6,9,8,4,3}构建的B树示意图,其中左侧灰色方块表示当前结点的元素个数:

(3)2-3B树
    2-3树是一个多路查找树,且其中的每一个结点都具有两个孩子(即2结点)和三个孩子(即3结点),2-3树中所有的叶子结点都在同一层次上。一个2结点包含一个元素和两个孩子(或没有孩子),一个3结点包含一小一大两个元素和三个孩子(或没有孩子)。

(4)2-3-4树
    为2-3树的概念扩展,包括了4结点的使用。一个4结点包含小大中三个元素和四个孩子(或没有孩子),一个结点要么没有孩子,要么具有4个孩子。如果某个4结点有孩子的话,左子树包含小于最小元素的元素;第二子树包含大于最小元素,小于第二元素的元素;第三子树包含大于第二元素,小于最大元素的元素;右子树包含大于最大元素的元素。

原创粉丝点击