数据结构

目录

二叉排序树的增删改查

平衡二叉树AVL

红黑树

B树

散列表

散列表与hashMap


二叉排序树的增删改查

平衡二叉树AVL

1.插入时单旋转
1)若当前节点,| 左子树高度-右子树高度 | >1,则开始准备旋转
a.若当前节点的左孩子的左孩子leftLeft高度 > leftRight ,则左单旋转
b.若当前节点的右孩子的右孩子rightRight高度 > rightLeft,则右单旋转
c. 若当前节点的左孩子的左孩子leftLeft高度 < leftRight , 则先将leftRight一支右单旋转,再整体左 单旋转
d.若当前节点的右孩子的右孩子rightRight高度 < rightLeft, 则先将rightLeft一支左单旋转,再整体

balance的代码为:

单旋转的代码为:

双旋转代码为:

红黑树

红黑树是AVL树的变种,其操作最坏情形下为log2N
1.红黑树的特征
1)根节点必须是黑色节点
2)从根节点到每一个叶子节点的路径上,都应该有相同的黑色节点
3)红色节点若有子节点,则必须两个子节点均为黑色节点
4)红黑树的高度最多为2log(N+1)
5)红黑树的优点是插入的开销相对低,而查找的效率几乎持平AVL树
2.红黑树的增删改查

 

B树

1.什么是M阶B树

 

散列表

在java中,参与散列的对象必须提供适当的equals方法与hashCode方法,散列表的核心概念为散列函数冲突处理方法装填因子,其中影响散列表查找效率的是装填因子,它代表散列表的饱满程度,饱满度越高,冲突可能性越大,查找的难度就越大。
处理冲突方法包括:拉链法和开放地址法,其中hashMap使用的是拉链法
1)拉链法:散列到同一位置的元素形成一个链,最新的元素放在链头,即使用头插法
2)开放地址法:包括线性探测法,平方探测法,再散列法,在频繁出现hash碰撞的情况下,拉链法肯定优于开放地址法

散列表与hashMap

hashMap采用的就是拉链法,涉及数据结构为数组(黄色部分,一格为一个桶),链表(绿色部分,一格一个节点),红黑树

分析hashMap的同样从其数据结构开始,包括一些基本性质,基本配置,散列函数,冲突解决方法,装载因子等

基本配置:

 

 

1.二叉查找树是TreeSet和TreeMap的实现基础

1)树如何实现操作系统的文件结构

2)树如何计算算数表达式的值

3)如何利用树支持logN平均时间的各种搜索操作,以及如何达到最坏情况时间界logN,并讨论当数据被存放到磁盘上时如何实现这些操作

4)TreeSet和TreeMap类

2.树的性质

3.二叉树的先序遍历,后序遍历,中序遍历

遍历的时间复杂度均为O(n) ,递归的次数正好是栈的深度

1)先序遍历:对节点的处理工作,在其子节点之前

2)后序遍历:对节点的处理工作,在其子节点之后

3)中序遍历:左中右

4)层次遍历

5)递归算法到非递归算法的转换

由先序遍历+中序遍历,后序+中序,层序+中序 = 唯一确定二叉树

4.二叉树的存储结构

1)顺序存储,用一连串相邻的地址空间存储元素,通过计算空间内的值来确定父子关系,适用于满二叉树和完全二叉树

2)链式存储:二叉链表,拥有n个节点的二叉链表就有n+1个空指针

3)线索二叉树:每一个节点新增全局变量leftTag,rightTag,若节点有左孩子,则leftTag=0,leftChild指向左孩子

,否则leftTag=1,leftChild指向其前驱,其前驱若没有右子树,则它的rightTag置1,rightChild指向其后继,也就是该节点

 

中序线索二叉树建立+遍历代码,线索二叉树的遍历代码,二叉排序树的构建与增删改查

 

1)双亲表示法:一张顺序表分为data和parent域,但这样找到一个双亲节点的所有孩子节点就需要遍历整张表

2)孩子表示法,顺序表存储每个节点,并指向其所有孩子节点的链表头地址,这样找到双亲节点的所有孩子节点就非常简单,叶子节点没有孩子节点,但如果要找到某个孩子节点的双亲节点,就要遍历所有孩子链

3)孩子兄弟表示法,一张图,它又叫二叉链表,任何非空树都可以找到唯一一棵二叉链表与其一一对应

5.二叉查找树=二叉排序树 -> 平衡二叉树(AVL带有平衡条件的二叉查找树)-> 哈夫曼树 (三者均为二叉排序树)

1)二叉排序树的增删改查(如果预先有序的序列形成二叉排序树,其查找效率将退化为O(N),如果成为平衡二叉树,则效率最高为log2N)

2)平衡二叉树(任意节点的左子树与右子树高度差的绝对值小于1)的增删改查

a.删除分3种情况:若待删除节点 为叶子,则直接删除;只有一个子节点,则父节点直接指向该孩子;有两个子节点,则交换该节点与该节点右子树中序遍历的第一个节点(右子树最小值),然后向其右子树递归删除

b.插入分为3种情况:

单旋转

双旋转

2)左子树与右子树高度差的绝对值小于1,则称为AVL树,平衡二叉树查找效率最高,log2N;单枝二叉树最低,为N

3)如果每个叶子节点的权重X其路径长度之和最小,则称之为哈夫曼树(最优二叉树)

4)哈夫曼算法构造最优二叉树

a.新增一个空节点,从节点集合中取权值最小的两个节点作为该节点的左右孩子,该空节点的权值变为其孩子的和

b.将上述新增空节点加入节点集合中,重复步骤a

B树

1.阶为M的B树的性质

2.访问佛罗里达公民驾驶记录,主键为32个字节,为什么使用B树而不用二叉查找树

3.B树的插入与删除

红黑树

 

2.红黑树的增删改查

若新增的节点为黑色节点:这显然不行,因为一旦加入,必然有一条路径黑色节点比其他路径多

若新增的节点为红色节点:

1)若其父节点为黑色节点,则成功加入

2)若其父节点为红色节点,则违反红色节点的孩子必须是黑色节点的原则,开始颜色的改变与树的旋转,参与者为父节点P,祖父节点G,新增叶子节点X,叔父节点S

a.若叔父节点S为黑色节点(空节点也作黑色处理),则开始单旋转或双旋转,并把新的根涂为黑色

b.若叔父节点S为红色节点,把根涂为黑色会导致出现两个相连的红色节点,所以根必须是红色。此时若曾祖父也是红色,那又得继续调整,这就叫上滤

散列表

由于不论线性表还是树,其查找都需要比对,如有一种key-value关系能直接查找到值,那就是散列表

 

泛型

1.泛型的主要目的是规定容器能持有什么样的对象,由编译器来保证类型的正确性

2.泛型容器能持有基类时,也能持有其子类

 

数组

1.数组是一个高效存储,随机访问的线性表,这种性能的代价是数组只能固定大小

2.数组中可以持有基本类型

3.数组中的数据类型必须为具体类型,无法通过new T[10] 这种形式创建泛型数组,但可以创建泛型数组的引用,如T[] a ,并通过它对非泛型数组进行转型

4.协变性

a是b的子类,则f(a)是f(b) 的子类

逆变性

a是b的子类,而f(a)是f(b) 的父类

数组具有协变性,即如下是正确的

B[] bs = new A[10];

泛型集合不具有协变性,即如下是错误的,会在编译期产生异常

List<B> bs = new ArrayList<A>

5.数组常用方法

//数组复制,指定新数组长度,如果新数组大于老数组,则填充0,效率高于for循环复制 Arrays.copyOf(int[] original, int newLength) //先判断数组大小是否相等,再挨个对比内部元素a==b //如果要深入对比里面的对象内容是否相等,需要重写equals和hasCode方法 Arrays.equals() //排序,如果要按对象的某个属性进行排序,该对象需要实现Comparable接口 Arrays.sort()

排序

1.1)几种容易算法均以o(n^2)完成排序

2)部分比较复杂的算法以o(nlogn) 完成排序

3)内排序,所有操作都在内存中完成

4)外排序,由于数据量太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行

5)时间复杂度:一个算法执行所消耗的时间

6)空间复杂度:运行一个程序所需要的内存大小

2.插入排序

1)插入排序由n-1趟排序组成,每插入一个数算一趟,每一趟完成一次排序

2)第N趟处理第N-1个元素,由于前N-2个元素已然有序,所以需要将第N-1个元素前移直到其正确位置,然后所有更大的元素后移一个位置

3.冒泡排序

1)比较相邻的元素,若第一个比第二个大,则交换他们两个

2)对每一对相邻的元素重复上述操作,到了最后,最大的肯定是最后一个

3)针对所有元素重复以上的步骤,除了最后那个,因为最后那个已经是最大的了

4)重复步骤1-3,直到排序完成

平均时间复杂度o(n^2),属于稳定排序,属于内部排序

4.选择排序

最简单的排序,不断从无序序列中找出最小(大)的元素,构成另外一个有序的序列,时间复杂度为o(n^2),是不稳定的

5.希尔排序

希尔排序是对插入排序的一种优化,平均时间复杂度o(nlogn),显然他是不稳定的

6.归并排序

归并排序在时间复杂度上优于选择排序,选择排序是稳定o(n^2),而归并排序是稳定o(nlogn),但它需要额外的内存空间,该算法是采用分治法的一个非常典型的应用

1)将

7.快速排序

快速排序也使用分治法,案例如下,平均时间复杂度为o(nlogn)

1)分别申请两个指针low和high,分别指向头和尾,并取low的值为基准数

2)从末端开始,若high的值>基准值,则high--,否则用high的值替换low指向的数

3)再交替为前端开始,若low的值<high的值,则low++,否则用low的值替换high的值

4)如此往复,直到low=high,则这个位置就是基准值得位置,最后小于基准值得数在基准值左边,大于基准值的数在基准值右边

5)递归处理左侧子序列和右侧子序列

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值