有序表学习笔记

有序表

有序表的分类

基于平衡搜索二叉树实现的有序表

搜索二叉树的节点的插入、查询、删除操作

搜索二叉树的节点的删除操作

(1)叶子节点直接删除;

(2)非叶子节点,删除之后,使用左子树最右的节点,或者右子树最左的节点填补空位。如果用左子树最右的节点,其左子树向上填补它移走后的空缺。如果用右子树最左的节点,其右子树向上填补它移走后的空缺。

删除50这个节点,可以用40或者60填补上去。如果用40填补,35补到40原先的位置。如果用60填补,65补到60原先的位置。

左旋和右旋

左旋和右旋用来调整二叉树的高度,通过适当的旋转操作可以让二叉树达到平衡。

对于搜索二叉树,左旋、右旋之后仍然是搜索二叉树。

左旋

节点T左旋,T向左侧倒:

(1)R成为新的头结点;

(2)T成为R的左子树,T的左子树不变,T的右子树为空;

(3)R的右子树T4不变;

(4)R原先的左子树T3挂到T的右侧。

右旋

节点T右旋,T向右侧倒:

(1)L成为新的头结点;

(2)T成为L的右子树,T的右子树不变,T的左子树为空;

(3)L的左子树T1不变;

(4)L原先的右子树T2挂到T的左侧。

平衡搜索二叉树实现有序表的原理

AVL树、Size-balanced-tree、红黑树都是利用平衡搜索二叉树的思想实现的有序表。

这三种有序表使用的搜索二叉树的查询,插入、删除节点,左旋,右旋等基本操作都是一样的,不一样的是它们对平衡性的定义,控制平衡的规则不一样。

AVL树严格遵守平衡二叉树的定义,通过树的高度、左旋和右旋调整平衡。

Size-balanced-tree不严格遵守平衡二叉树的定义,通过树的节点个数、左旋和右旋调整平衡,整体上保持平衡。

红黑树也不严格遵守平衡二叉树的定义,通过节点的颜色和个数、左旋和右旋调整平衡,整体上保持平衡。

二叉树搜索树加上平衡性约束(即使是整体上的平衡)后,整棵树可以认为是满二叉树,查找、插入、删除操作的时间复杂度为O(logN)。

AVL树

平衡性:

任意一个节点的左子树和右子树的高度差不超过1。

有四种形态的调整:LL、RR、LR、RL型。

Size-balanced-tree

平衡性:

每棵子树的大小,不小于其兄弟的任一子树的大小;

每棵叔叔树的大小,不小于任一侄子数的大小。

也是四种形态的调整:LL、RR、LR、RL型。

红黑树

平衡性:

每个节点都有一种颜色:红色、黑色;

头结点为黑色;

叶子节点为黑色;

红色节点不能相邻;

从每一个节点出发往下走,每条到结束的路上黑色节点数目一样多。

注意:

红黑树中的叶子节点是null节点,不是指既没有左子树、也没有右子树的节点

有八种形态的调整:略。

下边是一棵红黑树,但是并不是严格的平衡二叉树。

跳表

查找、插入、删除的时间复杂度O(logN)。跳表的索引有冗余,增加空间开销。

跳表节点的数据结构如下。跳表是多链表结构,每个节点至少有一个指向下一个节点的指针。

public class SkipList { public static class SkipListNode<K extends Comparable<K>, V> { public K key; public V value; public ArrayList<SkipListNode<K, V>> nextNodes; }}

头节点(默认节点)

逻辑上最小的节点,头结点不保存正常的数据,索引指针数可以动态扩充。

数据节点

除头节点之外存储数据的节点,数据节点的索引指针数固定不变。

数据节点索引指针数生成算法

指针数初始为1。随机从0,1两个数中取一个数(取到0和1的概率相等,都是50%),如果取到1指针数加1,继续该过程,如果取到0停止获取。

查找

从头结点开始,从上到下,从左到右的顺序查找。

从上图所示的跳表中查找节点40,查找过程如下:

(1)当前节点cur来到头节点

(2)从cur(头)的最高层开始,从第4层向右找到节点70,>40,在cur(头)处向下一层移动;

(3)来到cur(头)的第3层,向右找到70,>40,在cur(头)处向下一层移动;

(4)来到cur(头)的第2层,向右找到30,<40,cur移动到30这个节点;

(5)从cur(30)的最高层,从第2层向右找到70,>40,在cur(30)处向下一层移动;

(6)来到cur(30)的第1层,向右找到70,>40,在cur(30)处向下一层移动;

(7)来到cur(30)的第0层,向右找到50,>40,到达最下层,没有找到40,查找结束。

插入

在上图所示的跳表中插入节点40,插入过程如下:

(1)为40这个新节点生成索引指针的个数,假设生成的是6个,> 头节点的指针数(4);

(2)将头节点的指针数扩充到6个,新增加的2个指针先指向null;

(3)当前节点cur来到头结点,从最高层第6层开始,指向null,改成指向新节点40,在cur(头)处向下一层移动;

(4)来到cur(头)的第5层,指向null,改成指向新节点40,在cur(头)处向下一层移动;

(5)来到cur(头)的第4层,指向节点70,>40,将40插入cur(头)和70之间,在cur(头)处向下一层移动;

(6)来到cur(头)的第3层,指向节点70,>40,将40插入cur(头)和70之间,在cur(头)处向下一层移动;

(7)来到cur(头)的第2层,指向节点30,<40,cur移动到节点30,从cur(30)的最高层第2层开始,指向节点70,>40,将40插入cur(30)和70之间,在cur(30)处向下一层移动;

(8)来到cur(30)的第1层,指向节点70,>40,将40插入cur(30)和70之间,在cur(30)处向下一层移动;

(9)来到cur(30)的第0层,指向节点50,>40,将40插入cur(30)和50之间,已来到最下一层,插入完成。

删除

在上图所示的跳表中删除节点40,删除过程如下:

(1)在跳表中查找40,如果找不到,删除结束;

(2)当前节点cur来到头结点,从最高层第6层开始,指向40,40节点指向null,释放第6层,头结点层高减少1层;

(3)来到cur(头)的第5层,指向40,节点40指向null,释放第5层,头结点层高再减少1层;

(4)来到cur(头)的第4层,指向40,节点40指向节点70,cur(头)的第4层改成指向节点70,在cur(头)处向下一层移动;

(5)来到cur(头)的第3层,指向40,节点40指向节点70,cur(头)的第3层改成指向节点70,在cur(头)处向下一层移动;

(6)来到cur(头)的第2层,指向30,<40,cur移动到节点30,从cur(30)的最高层第2层开始,指向节点40,节点40指向节点70,cur(30)的第2层改成指向节点70,在cur(30)处向下一层移动;

(7)来到cur(30)的第1层,指向40,节点40指向节点70,cur(30)的第1层改成指向节点70,在cur(30)处向下一层移动;

(8)来到cur(30)的第0层,指向40,节点40指向节点50,cur(30)的第0层改成指向节点50,已来到最下一层,删除完成。

时间复杂度分析

每个数据节点的索引指针数通过每次50%的随机概率产生,如果总共有N个节点,则节点数的分布情况如下

第0层:N

第1层:N/2

第2层:N/4

第3层:N/8

等等......

整体上符合一棵满搜索二叉树,即平衡搜索二叉树,故查询、插入、删除的时间复杂度与平衡搜索二叉树相当,为O(logN)。

跳表的实现比平衡二叉树简单。

缺点:

索引指针数冗余存储,索引指针的空间复杂度是O(N*N),利用空间换时间。

参考资料

《bilibili左程云算法课堂》

《跳跃表Skip List的原理和实现(Java)》 https://blog.csdn.net/DERRANTCM/article/details/79063312

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Redis全套学习笔记.pdf》是一本关于Redis数据库的学习笔记,内容涵盖了Redis的基本概念、原理、操作、应用等方面的知识。 首先,Redis是一种开源的内存数据库,它具有高性能、高可用性和高扩展性的特点。它可以用于缓存、消息队列、实时排行榜等场景,广泛应用于Web应用开发、大数据存储和分析等领域。 在学习笔记中,首先介绍了Redis的基本概念,包括数据结构、持久化、单线程架构等方面的知识。数据结构包括字符串、哈希、列、集合和有序集合等,笔记详细介绍了它们的特点和使用方法。持久化方面,介绍了RDB快照和AOF日志两种持久化方式的原理和使用方法。同时,笔记也解释了为什么Redis选择单线程架构以及如何充分利用单线程的优势。 其次,学习笔记还包括了Redis的常用操作,例如数据的增删改查、事务和管道操作、过期时间设置等。这些操作是使用Redis进行开发和使用时必不可少的知识点,通过学习笔记可以快速掌握这些操作的使用方法。 此外,学习笔记还涉及了Redis的高级应用,如发布订阅、Lua脚本、事件通知等。这些高级应用可以帮助开发者更好地利用Redis的功能和特性,提升系统的性能和稳定性。 综上所述,《Redis全套学习笔记.pdf》是一本全面介绍Redis的学习资料,通过学习这本笔记,读者可以了解Redis的基本概念和原理,掌握Redis的常用操作和高级应用,从而更好地使用Redis进行开发和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值