数据结构与算法 简记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ty497122758/article/details/78895382
当有一个出栈,有一个就进栈的情况,可以用一个数组的两端来存储两个栈
用栈可以消除递归
为什么我的迭代比递归慢呢?
二叉树
满二叉树
节点要么是有两个子节点,要么就是叶子节点
Huffman编码就是满二叉树
特性:非空满二叉树的叶节点等于分支节点数加1
完全二叉树
新增节点都是从左到右,添加叶子节点,直到一层添加满,再起一层。
堆就是完全二叉树,堆经常用来实现优先队列和外排序算法。
完全二叉树直接用数组实现最紧凑
指针方式实现
叶子节点和分支节点是否使用相同的结构这点很重要,有些应用分支节点不存储数据,还有一些应用分支节点和叶子节点存储不同的数据
二叉树
删除:
  • 先查找,没有找到就放弃删除
  • 当待删除节点没有子节点,直接删除;
  • 当待删除节点只有一个节点,直接将子树指向待删除节点的父节点
  • 当待删除有两个节点,如果二叉树不允许重复元素出现,则将左子树的最大值或右子树的最大值代替待删除节点即可;但是如果允许重复元素出现,则只能用右子树最小值代替,因为左子树可能出现二个相同的元素,替换之后,左子树就出现了和父节点相同值得元素,这样是不允许的,因为相同的值我们要插入有子树
插入:
找到需要放的叶子节点,把parent指针指向叶子节点成为新的叶子节点
平衡二叉树
AVL
伸展树
堆(最大堆)
定义:父节点把所有子节点都大的完全二叉树,两个子节点之间没有大小关系限制
插入:
放在数组最后
如果比父节点小,则插入完成
如果比父节点大,则和父节点交换,然后再继续比较父节点,直到最后小于父节点
删除:
删除本身,用数组的最后一个填充,如果不满足堆性质,则下拉即可
多叉树
父节点,指向最左子节点和右兄弟节点
还可以用来表示森林,各根节点看做兄弟
树的顺序表示法
节省空间,方便把树序列化存储于磁盘或用于网络传输,特别是在分布式环境下,这种结构方便树结构的重建
用先序遍历方法遍历树,空节点用null表示,这样就实现了树的顺序表示法
空节点的数目=非空节点数目+1
内排序
简单低效率排序(n平方)
  • 插入排序
从第二个元素开始,依次和前面的元素比较,如果比前面小则交换,每一轮下来,前面都是排好序的
优势:对于已经接近排好序的序列,几乎可以接近为零的移动
  • 冒泡排序
从最后一个元素开始,依次和前面的元素比较,每一轮冒泡出一个最小的元素放在数组前面
  • 选择排序
选择排序其实就是冒泡排序,只是每次比较不交换元素,只记录最小值的下标,最后才把最小值交换到前面,交换次数比冒泡排序少,特别适合字符串或者其他大数据交换代价大的场景
希尔排序
是对插入排序的改进,不稳定的排序;虽然数据量特别大的情况下没有快速排序快,但是实现简单,在中等规模的场景比较适合,最差情况和最好情况相差不大;
算法思想:先对下标相隔1的排序(插入排序),然后在对相隔2,相隔4,相隔8,相隔16,直到达到数组长度
快速排序
是对冒泡排序的改进,不稳定的排序,分治思想;在大数据量下是最快的排序算法
算法思想:把数据分为两份(不一定均分),其中一份的所有数据比另一份数据的所有数据都小,然后递归每一份子数据
归并排序
基于bst(二叉排序树),稳定的排序,分治思想;速度仅次于快速排序
算法思想:先使子序列有序,再使子序列间有序
堆排序
基于选择排序,不稳定排序,分为大根堆、小根堆,比快速排序慢一个常数因子,但是堆排序最适合外排序,因为它建堆很快
左节点2i+1,右节点2i+2,最后一个非叶子节点为:arr.length/2 - 1
算法思想:
  1. 将无序序列构建成一个大顶堆。从最后一个非叶子节点开始,比较是否大于子节点,不大于和的话,就和最大的子节点交换,然后递归看交换了的子节点是否满足堆,否则就开始第二个非叶子的判断
  2. 将堆顶元素和末尾元素交换,第二次就和倒数第二个元素交换
  3. 重新调整堆结构,然后重复上面两个步骤
分配排序
桶排序,数的大小直接作为数组下标
外排序
简单外排序
采用双缓冲,两个输入缓冲,两个输出缓冲
数据最开始每个关键码算作一个有序串,第一轮把把关键码组合成有两个关键码的有序串,第二轮是四个关键码的有序串,第三轮是八个关键码的有序串,直到最后只剩一个有序串
两个有序串怎么合并成一个字符串?
首先取出两个串第一个关键码,这样可以得到最小关键码,这样剩下的关键码和另一个有序串的下一个关键码比较,得到第二小的关键码,以此类推
置换选择排序
是对简单外排序的两个串合并的优化,用一个长度为n的数组做堆的
首先建立一个满数组的小根堆,然后把堆顶关键码输出,这样可以新进来一个关键码,如果关键码比刚才堆顶的小,就放到数组最后,作为下一个堆的元素,这轮就不输出,否则就放到堆顶,重新调整堆,输出最当前的最小关键码
多路归并排序
是在置换选择排序的基础上继续优化,把两个串的合并,改为多个串的合并
检索技术
二分查找
自组织线性表
最不频繁使用(LFU)
最近最少使用(LRU)
转置,使用一次就前进一下
位图
散列表
索引
平衡二叉树操作
左旋:x节点的右子树y逆时针旋转,成为x节点的父节点,同时y的左子树成为x的右子树
右旋:x节点的左子树y顺时针旋转,成为x节点的父节点,同时y的右子树成为x的左子树
AVL树
平衡二叉树,允许任意节点的左右子树高度最多相差1
左左结构:右旋
右右结构:左旋
左右结构:左旋之后右旋
右左结构:右旋之后左旋
红黑树
是一种平衡二叉查找树,不像AVL那样严格平衡,执行插入所需开销比AVL树小,平均深度和AVL一样,两个兄弟子树的高度比不会超过两倍
特性:
每个节点要么红色,要么黑色
根节点是黑色
红色节点的孩子必须是黑色(所以黑色节点的孩子可以为黑色)
每个节点到最后一层节点的左右子树包含的黑色节点数目相同
插入(自下而上):
  1. 涂成红色(因为涂成黑色必然导致黑路径路大)
  2. 如果父节点是黑色,则插入完成
  3. 如果父节点是红色,父节点的兄弟节点是黑色,可以采用左旋右旋或者左右旋的方式解决
  4. 如果父节点是红色,父节点的兄弟节点也是红色,把父节点和父节点的兄弟节点变成黑色,祖父节点变为红色,由于祖父的父节点也可能为空红色,所以要向上回溯
插入(自上而下):
在自下而上插入的d步骤改为自上而下,遇到两个红色兄弟节点,就把红色节点改为黑色,父节点改为红色,如果父节点的祖父节点也为红色,则执行一次上面的c步骤
删除:
自上而下进行,每一次删除都可以替换为删除一个叶节点
如果叶节点是红色的,直接删除

伸展树:
是一颗二叉树,但是插入的时候不进行平衡调整,在进行访问的时候才进行调整,不是平衡二叉树
访问到的节点,向上回溯,执行像AVL树一样的旋转
好处:不仅把访问节点移动到了根处,而且还把访问路径上的大部分节点的高度降低了一半
2-3树
内部节点可以有最多两个关键码和最多三个叶节点,叶节点都在最下层,左子树的值小于左关键码,中子树大于等于左关键码,小于右关键码,右子树的值大于等于右关键码
2-3树就是一个3阶B树
B树
特性:
  • 数据存在树叶上(代表一个磁盘区块)
  • 根或者是叶节点,或者至少有两个子女
  • 每个内部节点最多有m-1个关键码
  • 每个内部节点有ceiling(m/2)到m个子女
  • 所有的叶节点在树的同一层,并有floor(L/2)和L之间个数据项
真实应用中,为了填充满一个磁盘块,一般都是大于100个子女
插入:
  • 沿根节点向下确定是放在哪个叶节点
  • 如果叶节点没满就直接放入
  • 如果满了,就要拆分成两个叶节点,同时更新父节点索引
  • 如果父节点也满了,继续向上分解直到根节点
  • 如果节点满了,就分成两个节点,这就是为什么根节点只要最少两个子节点就行,插入可以增加数的高度
删除:
  • 找到节点所在的叶节点,如果删除后大于半满,就直接删除
  • 如果小于半满,就要邻节点领养
  • 如果领养导致父节点索引小于半满,则采用相同的领养策略
  • 如果根节点小于一个节点,则删除根节点,所以删除节点,可以降低树的高度
B+树
特性:
是B树的变体
叶子节点一般链接起来,形成一个双链表

猜你喜欢

转载自blog.csdn.net/ty497122758/article/details/78895382
今日推荐