前言:记录了总6w字的面经知识点,文章中的知识点若想深入了解,可以点击链接学习。由于文本太多,按类型分开。这一篇是数据结构常问问题总结,有帮助的可以收藏。
1.栈和堆的区别:
- GC方面:栈保持着先进后出的原则,是一片连续的内存域,有系统自动分配和维护,产生的垃圾系统自动释放。而堆是无序的,他是一片不连续的内存域,用户自己来控制和释放,如果用户自己不释放的话,当内存达到一定的特定值时,通过垃圾回收器(GC)来回收。
- 存储方面:栈通常保存着我们代码执行的步骤,如方法变量等等。而堆上存放的则多是对象,数据等。我们可以把栈想象成一个接着一个叠放在一起的盒子(越高内存地址越低)。当我们使用的时候,每次从最顶部取走一个盒子,当一个方法(或类型)被调用完成的时候,就从栈顶取走接着下一个。堆则不然,像是一个仓库,储存着我们使用的各种对象等信息,跟栈不同的是他们被调用完毕不会立即被清理掉。
- 缓存方面:栈使用的是一级缓存,他们通常都是被调用时处于存储空间中,调用完毕立即释放;堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
- 存储方面:栈(Stack)是一种先进后出的数据结构,在内存中,变量会被分配在栈上来进行操作。堆(heap)是用于为引用类型的实例(对象),分配空间的内存区域,在堆上创建一个对象,会将对象的地址传给栈上的变量(反过来叫变量指向此对象,或者变量引用此对象)-----也就是栈上的变量指向了堆上地址为XXX的实例(对象)。
2.栈溢出一般是由什么原因导致的
- 无限递归。函数递归调用时,系统要在栈中不断保存函数调用时的现场和产生的变量,如果递归调用太深,就会造成栈溢出,这时递归无法返回。再有,当函数调用层次过深时也可能导致栈无法容纳这些调用的返回地址而造成栈溢出。
- 无限循环。
- 大量局部变量分配。
3.Stack栈和Queue队列
相同点:
- 都是线性结构。
- 插入操作都是限定在表尾进行。
- 都可以通过顺序结构和链式结构实现。
- 插入与删除的时间复杂度都是O(1),在空间复杂度上两者也一样。
- 多链栈和多链队列的管理模式可以相同。
- 底层都是由泛型数组实现。
不同点:
- 栈先进后出,队列先进先出:删除数据元素的位置不同,栈的删除操作在表尾进行,队列的删除操作在表头进行。
- 顺序栈能够实现多栈空间共享,而顺序队列不能。
- 应用场景不同
常见栈的应用场景包括
- 括号问题的求解,
- 深度优先搜索遍历等;
- 函数调用和递归实现,
- 表达式的转换和求值
常见的队列的应用场景包括
- 计算机系统中各种资源的管理,
- 消息缓冲器的管理
- 广度优先搜索遍历等
4.链表
单双向链表的区别:
指向不同:单向链表只有一个指向下一结点的指针,双向链表除了有一个指向下一结点的指针外,还有一个指向前一结点的指针。
功能不同:单向链表只能next ,双向链表可以return。
单双向不同:单链表只能单向读取,双向链表可以双向遍历。
单向链表优缺点:
优点:单向链表增加删除节点简单。遍历时候不会死循环;
缺点:只能从头到尾遍历。只能找到后继,无法找到前驱,也就是只能前进。
双向链表优缺点:
优点:可以找到前驱和后继,可进可退;
缺点:增加删除节点复杂,多需要分配一个指针存储空间。
s->prior=p; s->next=p->next; p->next->prior=s; p->next=s;
例题:遍历一遍找到链表倒数第 k 个元素
由于单链表只能从头到尾依次访问链表的各个节点,所以如果要找链表的倒数第 k 个元素,也只能从头到尾遍历查找。