多叉树 最长路径 java_Java面试题 - 数据结构与算法 - 小黑电脑

1. 说⼀下⼏种常⻅的排序算法和分别的复杂度

【快速排序】

原理:快速排序采⽤的是⼀种分治的思想,它先找⼀个基准数(⼀般选择第⼀个值),然后将⽐这个基准数⼩的数字都放到它的左边,然后再递归调⽤,分别对左右两边快速排序,直到每⼀边只有⼀个数字.整个排序就完成了.

选定⼀个合适的值(理想情况中值最好,但实现中⼀般使⽤数组第⼀个值),称为“枢轴”(pivot)。

基于这个值,将数组分为两部分,较⼩的分在左边,较⼤的分在右边。

可以肯定,如此⼀轮下来,这个枢轴的位置⼀定在最终位置上。

对两个⼦数组分别重复上述过程,直到每个数组只有⼀个元素。

排序完成。

复杂度:O(n)

特点:快速排序是我们平常最常使⽤的⼀种排序算法,因为它速度快,效率⾼,是最优秀的⼀种排序算法.

【冒泡排序】

原理:冒泡排序其实就是逐⼀⽐较交换,进⾏⾥外两次循环,外层循环为遍历所有数字,逐个确定每个位置,⾥层循环为确定了位置后,遍历所有后⾯没有确定位置的数字,与该位置的数字进⾏⽐较,只要⽐该位置的数字⼩,就和该位置的数字进⾏交换.

复杂度:O(n^2),最佳时间复杂度为O(n)

特点:冒泡排序在我们实际开发中,使⽤的还是⽐较少的.它更加适合数据规模⽐较少的时候,因为它的效率是⽐较低的,但是优点是逻辑简单,容易让我们记得.

直接插⼊排序:

原理:直接插⼊排序是将从第⼆个数字开始,逐个拿出来,插⼊到之前排好序的数列⾥.

复杂度:O(n^2),最佳时间复杂度为O(n)

直接选择排序:

原理:直接选择排序是从第⼀个位置开始遍历位置,找到剩余未排序的数据⾥最⼩的,找到最⼩的后,再做交换

复杂度:O(n^2)

特点:和冒泡排序⼀样,逻辑简单,但是效率不⾼,适合少量的数据排序。

2. ⽤java写⼀个冒泡排序算法

157162785d46957f6cea98cd672a7ab5.png

3. 描述⼀下链式存储结构

a. 线性结构的优点是可以实现随机读取,时间复杂度为O(1),空间利⽤率⾼,缺点是进⾏插⼊和删除操作时⽐较麻烦,时间复杂度为O(n),同时容量受限制,需要事先确定容量⼤⼩,容量过⼤,浪费空间资源,过⼩不能满⾜使⽤要求,会产⽣溢出问题。

b. 链式存储结构的优点主要是插⼊和删除⾮常简单,前提条件是知道操作位置,时间复杂度是O(1),但如果不知道操作位置则要定位元素,时间复杂度为O(n),没有容量的限制,可以使⽤过程中动态分配的分配内存空间,不⽤担⼼溢出问题,但是它并不能实现随机读取,同时空间利⽤率不⾼。

4. 如何遍历一颗二叉树

178f36fd1955566cf1b5f5d4ed38c8cd.png

树节点:

0988be52203244fcf251bb57ded6ef88.png

b. 递归先序遍历:先输出节点的值,再递归遍历左右⼦树。中序和后序的递归类似,改变根节点输出位置即可。

30e52d3206038b8cb38b3feac94504fb.png

c. 递归中序遍历:过程和递归先序遍历类似

4bb7f11aa20e8454b43bc960f4b8e411.png

d. 递归后序遍历:

a20bcf7d7abe18ef24fc5a4567234dbb.png

5. 倒排⼀个LinkedList

Collections.reverse(linkedList);

6. ⽤java写⼀个递归遍历⽬录下⾯的所有⽂件(directory.listFiles())

05d3ab7c23ed1aed7d7197d4aafbad55.png

7. ⼆叉树与红⿊树

⼆叉树

a7fae05cbd05d2c6f6378a56ffe7a1ac.png

特性:

左⼦树上所有结点的值均⼩于或等于它的根结点的值。

右⼦树上所有结点的值均⼤于或等于它的根结点的值。

左、右⼦树也分别为⼆叉排序树。

查找:

⼆分查找(通过⼀层⼀层的⽐较⼤⼩来查找位置):如查找值为10的节点:9–13–11–10

缺陷:

插⼊容易变成线性形态,查找性能⼤打折扣,这时需要引⼊红⿊树来解决

红黑树

33a1639d27dee75b8e86659391f02d90.png

特点:是⼀种⾃平衡的⼆叉查找树,除了符合⼆叉树的特点之外,还符合以下⼏点:

节点是红⾊或⿊⾊。

根节点是⿊⾊。

每个叶⼦节点都是⿊⾊的空节点(NIL节点)。

每个红⾊节点的两个⼦节点都是⿊⾊。(从每个叶⼦到根的所有路径上不能有两个连续的红⾊节点)

从任⼀节点到其每个叶⼦的所有路径都包含相同数⽬的⿊⾊节点。

这些规则保证了红⿊树的⾃平衡。

红⿊树从根到叶⼦的最长路径不会超过最短路径的2倍。

提⾼寻址效率。

添加删除:通过⾃旋来保证平衡

8. b-tree、b+tree多叉树

b-tree(⽂件系统)

B树也称B-树,它是⼀颗多路平衡查找树。我们描述⼀颗B树时需要指定它的阶数,阶数表示了⼀个结点最多有多少个孩⼦结点,⼀般⽤字⺟m表示阶数。当m取2时,就是我们常⻅的⼆叉搜索树。

定义:

1)每个结点最多有m-1个关键字。

2)根结点最少可以只有1个关键字。

3)⾮根结点⾄少有Math.ceil(m/2)-1个关键字。

4)每个结点中的关键字都按照从⼩到⼤的顺序排列,每个关键字的左⼦树中的所有关键字都⼩于它,⽽右⼦树中的所有关键字都⼤于它。

5)所有叶⼦结点都位于同⼀层,或者说根结点到每个叶⼦结点的⻓度都相同。

a8cd1fefcdcdf81ea4f6c4bedf8994e0.png

插⼊数据,向兄弟节点借,兄弟节点不够则向⽗节点借;

b+tree(mysql索引)

定义:

1)B+树包含2种类型的结点:内部结点(也称索引结点)和叶⼦结点。根结点本身即可以是内部结点,也可以是叶⼦结点。根结点的关键字个数最少可以只有1个。

2)B+树与B树最⼤的不同是内部结点不保存数据,只⽤于索引,所有数据(或者说记录)都保存在叶⼦结点中。

3)m阶B+树表示了内部结点最多有m-1个关键字(或者说内部结点最多有m个⼦树),阶数m同时限制了叶⼦结点最多存储m-1个记录。

4)内部结点中的key都按照从⼩到⼤的顺序排列,对于内部结点中的⼀个key,左树中的所有key都⼩于它,右⼦树中的key都⼤于等于它。叶⼦结点中的记录也按照key的⼤⼩排列。

5)每个叶⼦结点都存有相邻叶⼦结点的指针,叶⼦结点本身依关键字的⼤⼩⾃⼩⽽⼤顺序链接。

9387ec6563329e239bb71ccd277bc3e7.png

9. 谈谈数据结构,⽐如TreeMap

TreeMap实现了红⿊树的结构。

10. 图的深度遍历和⼴度遍历

1、深度优先遍历:

ab438345296f587da63730da1664095d.png

2、⼴度优先遍历:

e5f23523bbf8665b285b92e96e06ac41.png

11. 介绍⼀下红⿊树、⼆叉平衡树

12. 说说java集合,每个集合下⾯有哪些实现类,及其数据结构。

HashMap:

1d3af4cc9ccb78d61705bb0d3d5f0f52.png

在HashMap内部,采⽤了数组+链表的形式来组织键值对Entry(利⽤数组的查询快+链表的插⼊删除快)

HashMap在存储键值对Entry的时候,会根据Key的hashcode值,以某种映射关系,决定应当将这对键值对Entry存储在HashMap中的什么位置上

在JDK1.7进⾏多线程put操作,之后遍历,直接死循环,CPU飙到100%,在JDK 1.8中进⾏多线程操作会出现节点和value值丢失,为什么JDK1.7与JDK1.8多线程操作会出现很⼤不同,是因为JDK 1.8的作者对resize⽅法进⾏了优化不会产⽣链表闭环。

结构:

fef85ed8b9f03c89dd7cf3ea99c7d277.png

HashMap扩容:

ce25dbe1dc8c829ff7a5fe5a8f32383b.png

1、很简单的计算:由于默认的加载因⼦是0.75 ,那么,此时map的阀值是 16*0.75 = 12,即添加第13个键值对的时候,map的容量会扩充⼀倍。

2、确实如此,但是为了尽可能第减少桶中的Entry链表的长度,以提⾼HashMap的存取性能,确定的这个经验值。如果读者你对存取效率要求的不是太⾼,想省点空间的话,你可以new HashMap(int initialCapacity, float loadFactor)构造⽅法将这个因⼦设置得⼤⼀些也⽆妨。

扩容步骤:

c78bf039646a3acc675512994df2b182.png

2. 为何扩容为原来的两倍(性能):

在HashMap通过键的哈希值进⾏定位桶位置的时候,调⽤了⼀个indexFor(hash, table.length

87064361d62647f79d5c14a82fb1e05d.png

通过限制length是⼀个2的幂数,h & (length-1)和h % length结果是⼀致的。

如果length是⼀个2的幂的数,那么length-1就会变成⼀个mask, 它会将hashcode低位取出来,hashcode的低位实际就是余数,和取余操作相⽐,与操作会将性能提升很多。

put流程:

a. 获取这个Key的hashcode值,根据此值确定应该将这⼀对键值对存放在哪⼀个桶中,即确定要存放桶的索引;

b.遍历所在桶中的Entry链表,查找其中是否已经有了以Key值为Key存储的Entry对象,

c1. 若已存在,定位到对应的Entry,其中的Value值更新为新的Value值;返回旧值;

c2.若不存在,则根据键值对创建⼀个新的Entry对象,然后添加到这个桶的Entry

d.当前的HashMap的⼤⼩(即Entry节点的数⽬)是否超过了阀值,若超过了阀值(threshold), 则增⼤HashMap的容量(即Entry[] table 的⼤⼩),并且重新组织内部各个Entry排列。

get流程:

a. 获取这个Key的hashcode值,根据此hashcode值决定应该从哪⼀个桶中查找;

b.遍历所在桶中的Entry链表,查找其中是否已经有了以Key值为Key存储的Entry对象,

c1. 若已存在,定位到对应的Entry,返回value c2. 若不存在,返回null;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值