您的位置:首页 > 理论基础 > 数据结构算法

数据结构与算法复习笔记

2017-03-11 10:26 316 查看
算法分析

表栈和队列
1 抽象数据类型

2 表ADT

3栈

4 队列


1 二叉树

2 ADT查找树

3 AVL树

4 伸展树

5 树的遍历

5 B树

6 Set和Map

散列

优先队列堆
1 堆概述

2 二叉堆

3 左式堆

排序

不相交集类

图论算法

算法设计技巧

1. 算法分析

2. 表、栈和队列

2.1 抽象数据类型

什么是ADT:

2.2 表ADT

前继和后继

ArrayList和LinkedList特点:

ArrayList查找和修改速度快,插入和删除速度慢,因其使用数组实现,对于插入/删除点后的元素需要重新给id赋值,但查找和修改可以根据下标直接操作。

LinkedList插入和删除速度快,查找速度慢,因其用双向链表,插入/删除不只影响相邻点,但查找/修改需要从头/尾遍历。

3.3栈

先进后出

中缀转后缀:

操作数直接转输出

操作符使用栈处理

新操作符与栈顶元素比较,若优先级小于等于栈顶,则栈顶弹出。然后新操作入栈,否则新操作符直接压入。

对于”(“,直接入栈,只有在新操作符为“)”时,将其上所有元素弹出。

链表实现和数组实现

3.4 队列

先进先出

数组实现

用于服务器区块的响应,使用排队论解决响应与阻塞问题。

3. 树

大部分树拥有O(logN)的平均深度。

深度:从根到nk的最短路径,高度:从nk到树叶的最长路径

根的深度为0,树叶的高度为0。

从n1到nk的节点序列为n1到nk的路径。

三种遍历:

先序遍历:先父节点,后左,最后右

中序遍历:先左,后父节点,最后右

后序遍历:先左,后右,最后父节点

3.1 二叉树

每个节点的子节点不超过2两个

一般使用二叉查找树

3.2 ADT查找树

左子树每一个节点小于右子树的每一个节点

二叉树类总是支持comparable 的接口,使用compareTo来比较树内的每一项

boolean contains(),BinaryNode findMin(),BinaryNode findMax()

BinaryNode insert():查找,若不重复则插入到最后查找点的左/右子节点。

BinaryNode remove():

若删除节点只有一个子节点,该子节点替代之

若有两个子节点,则寻找 右边最小项 替代之

对于有重复项的树,使用额外的空间(如表)记录节点频率

懒惰删除:仅标记为删除,节点频率减一,不实际从树中删去

3.3 AVL树

带有平衡条件的二叉查找树

|H(leftTree)−H(rightTree)|≤1

除了可能的插入操作外,其他操作(查询,修改,删除)的时间复杂度都为O(logN)

插入新点后再平衡的策略为:

从高度最大的不平衡子树的根节点开始:

若新插入点在左儿子的左子树或右儿子的右子树,使用单旋转

设不平衡子树的根节点为k1,过深子树的儿子为k2

将k1父节点作为k2父节点,k2 作为k1的父节点,k1作为 k2的左/右子节点

原 k2的左/右节点成为 k1的右/左节点

若新插入点在左儿子的右子树或右儿子的左子树,使用双旋转,双旋转等于两次单旋转,第一次对于不平衡子树的较深子树进行,第二次对于整个不平衡子树进行

设不平衡子树根节点为k1,该子树的较深子树根节点为k2,以k2作为根节点的子树的较深子树为k3。

先对较深子树(k2)进行一次单旋转,完成旋转后k3为该子树的根节点

再对以k1为根节点,k3为子节点的子树进行单旋转,结果k3成为根节点。

3.4 伸展树

保证M次操作时间:O(MlogN)

对于某一节点的访问将激活伸展操作

伸展操作的结果是该节点上升到根,收益为减少下次访问时间,同时可能减小树的深度

伸展操作分为“一字型”和“之字形”

设操作节点为X,其父节点为P,P的父节点为G

一字型:X与P的左右关系和P与G的左右关系相同

之字型:X与P的左右关系和P与G的左右关系不相同

若为之字形,从X开始向G做两次单旋转,否则从G向X 做两次单旋转,最终结果相同,X成为根节点

删除时,可访问某一节点,将其升到根节点后删去,并取其左子树的最大叶节点替代

3.5 树的遍历

先序遍历:中左右

中序遍历:左中右

后序遍历:左右中

层序遍历:从上到下

3.5 B树

B树是具有阶数M的不定叉树

B树主要处理的目的是使得树在一定程度上更扁平化,因为判断分支所的计算花销要远小于读取数据指令,通过增加分叉树来减少读取数据的次数。

一个具有M阶的B树具有以下特性:

根节点必须是一个叶节点或拥有2到M个子节点

每个非叶非根节点必须拥有[M2,M]个子节点

每个非叶节点使用M-1个关键字划分出M个子树

所有叶节点拥有同样的高度

每个叶节点包含一个数据块,包含[L2,L]个数据

一个M阶B树的结构定性如下:

设每个磁盘区块容量为D字节,每个数据占用X个字节

对于每个节点含有M-1个关键值,占用X∗(M−1)字节,同时分出M个子节点,使用4个字节记录每个子节点的磁盘地址。所以每个节点占用X∗(M−1)+4M=(X+4)∗M−X个字节的地址,受限于区块容量限制,有(X+4)∗M−X≤D,由此解出M。

对于叶节点,同样受限于区块容量限制,有L∗X≤D,求出L

B树的插入和删除

B树操作的最坏时间由logM2N近似给出有。

B树的插入操作:

简单的插入可能存在叶节点数据量大于L的问题。

当叶节点容量不足以加入新数据时,向上取父节点P,若P的关键数小于M-1,添加新的关键值进行分裂。否则,再继续向上尝试分裂父节点,直到成功为止。若到达根节点,则向上增加一层。

这是B树唯一的增高方式,也是根节点允许只拥有两个子树的原因。

另一种方式插入方式:

改变父节点的关键值,将合适的子树转入与父节点相邻的子树下。该方法使叶节点的数量区域饱和,适用于长时间运行的项目。

B树的删除操作:

简单删除存在叶节点的数据量小于L2的问题

同样的,可以在删除后从父节点的相邻子树领养一个数据来解决,当相邻节点已达到最小值时L2,则将该节点与相邻节点合并

节点合并可能会导致父节点的子树少于M2的情况,因此需要继续合并或领养。

当合并到达根节点的时候,不允许根节点仅有一个子节点,此时删除根节点,树高度减一。

这是唯一的减少树高度的方法。

3.6 Set和Map

Set接口是一种不允许值重复的Collection, TreeSet是保证数值有序的Set的实现

TreeSet提供自然排序和定制排序:

自然排序默认使用Object自带的Compare函数进行比较以确定是否重复。

定制排序在实例化时传入Camparetor实例来定义比较结果,0为相同

TreeSet由于数据的顺序性,提供first(),last(), subset(Obj, Obj), headset(Obj), tailSet(Obj), higher(Obj), lower(Obj)方法。

Map接口是由键值对构成的Collection,其中键是不可重复的,但是值可以,TreeMap是SortedMap的实现,其中的键是有序排列的。

4. 散列

5. 优先队列(堆)

5.1 堆概述

堆的作用是对最小元素进行常数时间的读取

堆一般主要用于顺序管理

堆的两性:

堆序性质:父节点恒小于等于左右子节点

结构性质:总是完全二叉树,叶节点从左到右填满

5.2 二叉堆:

二叉堆可以使用数组实现:任意节点 i 的子节点位于2i和2i+1上

二叉堆的插入/上滤(最坏O(logN)):

先插入末尾空位

检查是否符合堆序性质

若不符合则与父节点换位

重复2,3直到符合堆序性质

二叉堆的堆顶删除/下滤:

先删除堆顶节点

将末尾节点填入堆顶

检查是否符合堆序性质

若不符合,和较小的子节点换位

重复3,4直到满足堆序性质

5.3 左式堆

左式堆满足堆的堆序性质

左式堆的节点除了记录根节点,左右子节点外,还需要记录零路径长。

左式堆的结构性质:

零路径长npl(null path length):到最近不含双子节点的节点的距离

左式堆的任意左子节点的零路径长大于等于兄弟右节点的零路径长

左式堆的优点:

左式堆的合并排序

合并操作使用递归进行

将 根节点较大的子树H1 与 根节点较小子树的右子树H2 合并,返回值作为H2的新右子树

若其中一个子树为空,则返回另一子树

若H2左子树为空,则将H1作为H2的左子树,并返回

在迭代返回中,检测每个左右节点的npl,若不满足左式堆性质,则交换左右子树,并更新npl

排序

不相交集类

图论算法

算法设计技巧

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 算法 数据