重学数据结构笔记(3)

5.串,由零个或多个字符组成的序列,又叫字符串
串的比较是通过组成字符串的字符之间的编码来进行的,而字符串编码指的是字符在对应字符集中的符号。
串的存储结构与线性表相同分两种
串的顺序存储结构
串的顺序存储结构是用一组地址连续的存储单元来存储串中的字符序列的。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区域,一般使用定长数组来定义
串的顺序存储方式其实是有问题的,因为串的插入和替换都会引起长度超过数组长度。
串的链式存储结构,与线性表链式存储结构相似,不过每个节点存一个字符,太浪费空间,可以一个节点存多个字符,不够的用#补满
串的链式存储结构除了在链接串与串操作时有一定方便之外,总的来说不如顺序存储灵活,性能也不如顺序好。

朴素模式匹配算法
子串的定位操作通常称作串的模式匹配,算是串中最重要的操作了。
对主串的每个字符做为子串的开头,与要匹配的字符串匹配。对主串做大循环。直到全部遍历匹配成功为止。(效率太低)
平凡子串不包括自身
KMP算法(有点难,最后攻克)

6.树,树是n(n>=0)个结点的有限集,n=0时为空树,在任意一课非空树中:(1)有且仅有一个特定的称为根的结点,(2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集t1,t2,t3,t4.....tm,其中每一个集合本身又是一棵树,并且称为根的子树。
注意点,当n>0时根结点是唯一的,不可能存在多个根结点;;当m>0时,子树的个数没有限制,但他们一定是互相不交互的。
树的节点包含一个数据元素及若干指向其子树的分支。结点用有的子树数称为结点的 度 。度为0的结点称为 叶结点或终端结点;度不为0的结点称为非终端结点或分支结点。除根节点之外,分支结点也称为内部结点,树的度是数内各结点的度的最大度。
结点间的关系
结点的子树的根称为该结点的 孩子(Child),相应的,该结点称为孩子的双亲(Parent),同一个双亲的孩子之间互为兄弟(SibLing)
结点的层次从根开始定义起,根为第一层,根的孩子为第二层,以此类推,树中最大层次称为树的深度(Depth)或高度。
如果将树中结点的各个子树从左至右是有顺序的,那么他就是有序树,否则叫无序树。
森林(Forest)是m(m>0)课不相交树的集合。

树的存储结构、
双亲表示法:在每个结点中,附设一个指示器指示其双亲结点到数组中的位置。也就是说每个结点除了知道自己是谁外,还知道他的双亲在哪里。
在双亲表示法的基础上,如果有需要还可以增加孩子结点指针。
存储结构的设计是一个非常灵活的过程,一个存储结构设计的是否合理,取决于基于该存储结构的运算是否合适,是否方便,时间复杂度好不好等。。。
孩子表示法:把每个结点的孩子结点排列起来,以单链表作存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空,然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。
换一种完全不同的考虑方法,由于树中每个结点可能有多颗子树,可以考虑用多重链表,即每个结点有多个指针域,其中每个指针指向一科子树的根节点,我们把这中方法叫多重链表表示法。
不过由于每个结点的度不同,所以设计两种方案解决。
方案一,指针域的个数等于树的度。(会造成空间浪费,不过各结点的度相差较小时,意味着会充分利用)
方案二,每个结点的指针域个数等于该结点的度。(空间利用率高了,不过运算时间损耗相对大)
可以把双亲表示法和孩子表示法结合,双亲孩子表示法。
孩子兄弟表示法:任意一棵树,他的结点的第一个孩子存在就是唯一的,他的右兄弟存在也是唯一的。因此,我们设置两个指针,分别指向该结点的第一个孩子和此结点的右兄弟(第二个指针是由第一个孩子结点指向其右兄弟)。

二叉树(Binary Tree):是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两颗互不相交的、分别称为根结点的左子树和右子树的二叉树组成。
特点:每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点;;左子树和右子树是有顺序的,次序不能任意颠倒,就想人有左右手,不能颠倒;;即使树中某结点只有一棵树,也要区分他是左子树还是右子树(左手受伤和右手受伤,对生活的影响是不同的)
二叉树的五种基本形态:空二叉树;只有一个根节点;根节点只有左子树;根节点只有右子树;根结点左子树右子树都有;

特殊二叉树
斜树:所有结点只有左结点的二叉树叫左斜树,所有结点只有右节点的二叉树叫右斜树(其实与线性表结构一样,线性表结构可以理解为树的一种极其特殊的表现形式)
满二叉树:在一棵二叉树中,所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,我们叫它满二叉树。(特点:叶子只能出现在最下一层;非叶子结点的度一定是2;同深度的二叉树,满二叉树结点最多,叶子最多)
完全二叉树:对一棵具有n个结点的二叉树按层编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这课二叉树称为完全二叉树。(满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树,关键词:按层次编号!!)
完全二叉树特点:叶子的结点只能出现在最下层;最下层的叶子一定集中在左部连续位置;倒数第二层若有叶子结点,一定都在右部连续位置;如果结点度为1,则该节点只有左孩子不存在只有右孩子的情况;同样结点数的二叉树,完全二叉树深度最小;;

二叉树的五个性质:(用数据归纳法论证)
①在二叉树的第i层上至多有2i-1(2的i-1次方)个结点(i>=1)
②深度为k的二叉树至多有2k-1(2的k次方-1)个结点(k>=1)
③对于任意一课二叉树T,如果其终端结点(叶子)数量为n,度为2的结点个数为m,则 n=m+1。
④具有n个结点的完全二叉树的深度为|log2n|+1(log以2为底数n的对数+1)(|X|表示不大与X的最大整数,,,也就是取整)(由完全二叉树和满二叉树推到出来)
⑤如果对一棵有n个结点的完全二叉树(深度是④)的结点按层序编号(从1层到④层,每层从左到右),对任一结点i(1=<i<=n)有:
⑴若i=1,则结点i是二叉树的根,无双亲;若i>1,则其双亲是结点|i/2|
⑵如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩子是结点2i
⑶如果2i+1>n,则结点i无右孩子;否则右孩子是结点2i+1

二叉树顺序存储结构:将二叉树放入数组,下标对应二叉树的层序编号(特殊:一棵树深度为k的右斜树,他只有k个结点,却要分配2k-1空间,浪费),二叉树顺序存储结构只用于完全二叉树。
二叉链表:二叉树每个结点最多有两个孩子,所以设计一个数据域和两个指针域是比较自然的想法,我们称这样的链表叫二叉链表。(如同 树 的链式存储结构,如果有需要还可以加一个指向双亲的指针域,称为三叉链表)

二叉树的遍历:是指从二叉树的根结点出发,按照某种次序一次访问所有结点,使得每个结点仅被访问一次。关键词:访问 次序
二叉树遍历方法
前序遍历:若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。ABDGHCEIF(先打印结点,再左右递归)
中序遍历:若二叉树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。GDHBAEICF(先左递归再打印结点再右递归)
后序遍历:若二叉树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。GHDBIEFCA(先左右递归再打印结点)
层序遍历:若二叉树为空,则空操作返回,否则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。ABCDEFGHI
我们以图的形式来看树很直观和容易理解,但计算机只能处理,循环、判断,也就是说他只能循环线性列,所以有了不同的遍历方法,不同的遍历提供了对结点一次处理的不同方式,可在遍历过程中对结点进行各种处理。
二叉树遍历的性质:已知前序遍历序列和中序遍历序列,可以唯一确定一棵二叉树;;已知后序遍历序列和中序遍历序列,可以唯一确定一棵二叉树;;但是,已知前序序列和后序序列,是不能确定一棵二叉树的(因为不能知道那个是左子树,那个是右子树)
二叉树的建立,在内存中,为了让每个结点都有左右孩子,对不齐全的二叉树,为每个空指针引出一个虚拟结点,比如设置为“#”,这种二叉树称为原二叉树的扩展二叉树,扩展二叉树就可以做到一个遍历序列确定一棵二叉树,如AB#D##C##
生成二叉树,也是利用了递归的原理,只不过在原来打印结点的地方,改成了生成结点,赋值操作而已,跟3种遍历的原理一样。
建立二叉树后,因为是链式结构,而每个结点均有指向其左右孩子的指针,所以会出现空指针,造成空间浪费;
线索二叉树:我们把指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树就称为线索二叉树;
我们对二叉树以某种次序遍历使其变为线索二叉树的过程称作是线索化。
由于二叉树线索化后,无法知道其指针指向的是哪个,所以要再加两个标志域ltag rtag,当ltag为0时指向该节点的左孩子,当为1时指向该节点的前驱;rtag同理(右孩子)
线索化的过程就是在遍历的过程中修改空指针的过程。
在实际的问题中,如果所用的二叉树需要经常遍历或查找结点时需要某种遍历序列中的前驱和后继,那么采用线索二叉链表的存储结构是非常不错的。

树转为二叉树步骤:
①加线,在所有兄弟结点之间加一条线;
②去线,对树中每个结点,只保留它与第一个孩子的结点的连线,删除它与其他孩子结点之间的连线。
③层次调整,以树的根结点为轴心,将整棵树顺时针旋转一定的角度,使之结构层次分明,!注意第一个孩子是二叉树结点的左孩子,兄弟转换过来的孩子是结点的右孩子。
森林是由很多树组成
森林转为二叉树:
①把每个树转为二叉树;
②第一颗树不动,从第二颗二叉树开始,一次把后面一棵二叉树的根结点作为前一颗二叉树的根结点的右孩子,用线连接起来,当所有二叉树都连接起来后转换完成;
二叉树转为树:(树转为二叉树的逆向过程)
①加线,若某结点的左孩子存在,将这个左孩子的右孩子结点、右孩子孩子的结点、右孩子孩子孩子的结点......反反正是左孩子的n个右孩子结点都作为此结点的孩子,将该结点与这个右孩子结点用线连接起来。
②去线,删除原二叉树中的所有结点与右孩子结点的连线;
③层次调整;
二叉树转为森林:(判断一棵树二叉树是转换成一棵树还是森林,标准很简单,那就是只要看这课二叉树的根结点有没有右孩子,有就是森林,没有就是一棵树)
①从根结点开始,若右孩子存在,则删除根结点与右孩子的连线,再查看分离后的二叉树,若根结点右孩子存在,则删除根结点与右孩子的连线,一次类推,直到所有右孩子的连线都删除为止,得到分离的二叉树;
②再将分离的后的二叉树转为树即可;

树与森林的遍历
树:
一种是先根遍历,即是先访问树的根结点,再访问树的其他结点
一种是后根遍历,先访问遍历没颗子树,最后再访问根结点
森林:
前序遍历:先访问森林中第一棵树的根结点,再依次先根遍历根的没颗子树,再用同样的方式遍历其他树;
后序遍历:先访问森林中第一棵树,后根遍历每颗子树,再访问根结点,再用同样方式遍历其他树;

赫夫曼树
从树种一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称作路径长度。
树的路径长度就是从树根到每一结点的路径长度之和
假设有n个权值,构造一棵有n个叶子结点的二叉树,每个叶子结点带权w,每个叶子的路径长度为lk,则其中带权路径长度wpl最小的二叉树称作赫夫曼树。也有不少书中称为最优二叉树。

时间: 2024-10-08 17:52:35

重学数据结构笔记(3)的相关文章

重学数据结构笔记

大学上数据结构课都逃了,后来发现其重要,期间又自己抱起书学了一遍,因为当时懒,自学的成果也不大,如今工作有一年了,也写过几个项目越来越感觉数据结构对个人思想的重要,如今趁裸辞的空窗期,好好恶补下,顺便写个笔记总结下.仅为个人笔记用所以不排版写到哪算哪. 1,数据结构,是相互之间存在一种或多种关系的数据元素的集合从不同角度讨论,有不同的分类物理结构:顺序存储结构,链式存储结构逻辑结构:线性结构,集合结构,树形结构,图形结构2.数据类型,是指一组性质相同的值得类型的集合以及在此集合上的一些操作抽象数

重学数据结构笔记(2)

4.栈和队列栈(stack),是仅限定在表尾进行插入和删除操作的线性表 (一种特殊的线性表,有前驱后继关系)我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何元素的称为空栈,栈又称为先进后出的线性表简称LIFO结构先进后出,后进先出,最先进栈的元素不一定最后出,因为栈对元素的删除和增加位置有了限制,可时间没限制例子:1,2,3依次放入栈中,可能是 1进 1出 2进 2出 3进,3出 所以进栈顺序是123出栈顺序也是123,其他情况相似.但是一定不会有312出栈顺序(自己想为什么,很重要

重学数据结构系列之——平衡树之SB Tree(Size Blanced Tree)

平衡树 1.定义 对于每个结点,左右两个子树的高度差的绝对值不超过1,或者叫深度差不超过1 为什么会出现这样一种树呢? 假如我们按照1-n的顺序插入到二叉排序树中,那么二叉排序树就退化成了一个有序链表,效率大大降低. 2.有关概念 所有平衡树基本由以下三个特征组成: 1.自平衡条件 2.旋转操作 3.旋转的触发 平衡树通过设置合理的自平衡条件,使得二叉排序树的查找.插入等操作的性能不至于退化到 O(n)O(n),并且在进行二叉排序树的查找.插入等操作时进行判断,如果满足其中某个旋转的触发条件,则

重学数据结构 --- 分类+稀疏数组

一.数据结构的分类 1. 数据结构两大类 线性结构和非线性结构 1) 线性结构 线性结构是最常见的数据结构,特点是元素间存在一对一的线性关系. 线性结构又分两种,一种是顺序存储(称为顺序表),另外一种是链式存储(称为链表).顺序表中的存储元素的连续的.链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息. 常见的线性结构有:数组.队列.链表和栈(这里只是讲个大概,具体内容后面的文章会展开阐述). 2) 非线性结构 非线性结构就是结点元素可能存在多个直接前趋和多个直接后续(

C#&amp;java重学笔记(函数)

C#部分  1.写在函数定义的()中的关键字: a.params关键字:用来满足函数的参数为数组时,而数组的长度不固定的情况.且该关键字只能用来修饰数组型参数.这样一修饰,就达成了类似JavaScript函数书写参数的特点. b.ref关键字:让参数按引用传递,类似于C中的传指针参数.比如经典的数值交换函数,你传形参和传指针的结果应该知道,加了ref关键字就相当于传指针.注意:ref只接收变量做参数,你字面量怎么弄指针?而且该变量必须初始化!     c.out关键字:功能和ref一样,区别在于

C#&amp;java重学笔记(面向对象)

C#部分 1.C#有一个internal关键字,指字段可以同一个程序集中访问,出了程序集不行.还有一个protected internal(没有先后之分)修饰词,指只能在同一个程序集中的子类访问 2.abstract和virtual修饰词: abstract用来修饰类和方法,表 抽象.抽象类中的方法可以不抽象,但是抽象方法所在的类必抽象.且抽象方法不得被实现,即不能用{}表示函数体.而且抽象类只有被继承才能体现它的作用,同时子类必须override父类的抽象方法!      virtual用来修

C#&amp;java重学笔记(泛型)

C#部分: 1.泛型的出现主要用于解决类.接口.委托.方法的通用性,通过定义泛型类.接口.委托.方法,可以让不同类型的数据使用相同运算规则处理数据,方便了开发. 2.利用System.Nullable<T>泛型可以生成可空的值类型变量,值类型的可空泛型可以简写为关键字加问号,如:int? val=new int?(); 3.关于布尔类型的泛型可空& |操作,我们可以知道,如果关心不关心操作数是否为空就能得出结果,那么空值就是无所谓的. 4.可空的泛型值类型的HashValue属性值为t

48. 蛤蟆的数据结构笔记之四十八的有向无环图的应用关键路径

48. 蛤蟆的数据结构笔记之四十八的有向无环图的应用关键路径 本篇名言:"富贵不淫贫贱乐 ,男儿到此是豪雄.-- 程颢" 这次来看下有向无环图的另一个应用关键路径. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47135061 1.  关键路径 与AOV-网相对应的是AOE-网(Activity On Edge)即边表示活动的网.AOE-网是一个带权的有向无环图,其中,顶点表示事件(Event),弧表示活动,权表

重学线代——声明篇

为啥重学线代呢? 1.当初学得模棱两可,时间长了啥也没剩下 2.越来越发现线代很流弊,很有用(不只是线代,各门数学都有此感触) 3.比较巧合地在网络上发现了个很好的线代教学资源 4.假期浪费了太可惜了 你这堆博客要写点啥呢? 课程笔记.个人领悟.无知吐槽.等等等等 你还想说点啥么? 没了 哦 恩