介绍
数据结构是我们面试中经常会问到的一个问题,今天我们来简单介绍下我们常用的8中基本数据结构吧!
讲解流程:
一.数据结构的定义
二.8种基本数据结构
1.数组(Array)
2.链表(Linked List)
3.栈(Stack)
4.队列 (Queue)
5.树 (Tree)
6.图 (Graph)
7.散列表 (Hash)
8.堆 (Heap)
一.数据结构的定义
数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合,它研究的是数据的逻辑结构和数据的物理结构以及它们之间的相互关系,并对这种结构定义相适应的运算,设计出相应的算法,并确保经过这些运算以后所得到的新结构仍保持原来的结构类型。
数据结构分为线性数据结构、非线性数据结构
线性数据结构:数组,栈,链表,队列
非线性数据结构:树,图,堆,散列表
数据结构有很多种,一般来说,8种常用数据结构分别为:数组,栈,链表,队列,树,图,堆,散列表等,
二.8种基本数据结构
1.数组(Array)
数组是用于储存多个相同类型数据的集合。
数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按无序的形式组织起来的一种形式。这些无序排列的同类数据元素的集合称为数组。数组是最简单、也是使用最广泛的数据结构。栈、队列等其他数据结构均由数组演变而来。
int[] data = new int[100];
data[0]=2;
优点:按照索引查询元素速度快
缺点:
1.数组大小固定后无法扩容
2.数组只能储存一种数据类型
3.增、删数据操作,比较耗时。
使用场景:频繁查询,对存储空间要求不大,很少增加和删除的情况。
面试中常见问题
- 寻找数组中第二小的元素
- 找到数组中第一个不重复出现的整数
- 合并两个有序数组
- 重新排列数组中的正值和负值
2.链表(Linked List)
链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间),另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。
优点:
1.不需要初始化容量
2.可以添加任意元素
3.插入和删除时只需要更新引用
缺点:
1.含有大量引用,占用内存空间大;
2.查找元素需要遍历整个链表,耗时。
使用场景:数据量较小,需要频繁增加,删除操作的场景
数组与链表对比
3.栈(Stack)
栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作。从栈顶放入元素的操作叫入栈,取出元素叫出栈。
特点:后进先出
(1) 栈的基本操作
- Push——在顶部插入一个元素
- Pop——返回并移除栈顶元素
- isEmpty——如果栈为空,则返回true
- Top——返回顶部元素,但并不移除它
(2) 面试中关于栈的常见问题
- 使用栈计算后缀表达式
- 对栈的元素进行排序
- 判断表达式是否括号平衡
4.队列 (Queue)
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
栈与队列的最大差别在于栈是LIFO(后进先出),而队列是FIFO,即先进先出。
队列可以用数组来实现,也可以用链表来实现。用数组实现的栈叫作顺序栈,用链表实现的栈叫作链式栈。同样,用数组实现的队列叫作顺序队列,用链表实现的队列叫作链式队列。
特点:先进先出
应用场景:因为队列先进先出的特点,在多线程阻塞队列、循环队列、并发队列管理中非常适用。
面试中关于队列的常见问题
- 使用队列表示栈
- 对队列的前k个元素倒序
- 使用队列生成从1到n的二进制数
5.树 (Tree)
树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做 “树” 是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
树形结构被广泛应用于人工智能和复杂算法,它可以提供解决问题的有效存储机制。
- Root - 根节点
- Parent - 父节点
- Child - 子节点
- Leaf - 叶子节点
- Sibling - 兄弟节点
特点:
- 每个节点有零个或多个子节点
- 没有父节点的节点称为根节点
- 每一个非根节点有且只有一个父节点
- 除了根节点外,每个子节点可以分为多个不相交的子树
在日常的应用中,我们讨论和用的更多的是树的其中一种结构,就是二叉树。
二叉树是树的特殊一种,具有如下特点:
1、每个结点最多有两颗子树,结点的度最大为2。
2、左子树和右子树是有顺序的,次序不能颠倒。
3、即使某结点只有一个子树,也要区分左右子树。
二叉树是一种比较有用的折中方案,它添加,删除元素都很快,并且在查找方面也有很多的算法优化,所以,二叉树既有链表的好处,也有数组的好处,是两者的优化方案,在处理大批量的动态数据方面非常有用。
面试中关于树结构的常见问题
- 求二叉树的高度
- 在二叉搜索树中查找第k个最大值
- 查找与根节点距离k的节点
- 在二叉树中查找给定节点的祖先节点
6.图 (Graph)
图是一组以网络形式相互连接的节点。节点也称为顶点(Vertex)。 一对节点(x,y)称为边(edge),表示顶点x连接到顶点y。边可以包含权重/成本,显示从顶点x到y所需的成本。
图是由顶点集合(Vertex)及顶点间的关系集合组成的一种数据结构:Graph=( V, E )
V = {x | x ∈某个数据对象 } 是顶点的有穷非空集合;
E ={ (x, y) | x, y ∈V } 是顶点之间关系的有穷集合,也叫做边(Edge)集合。
按照顶点指向的方向可分为无向图和有向图:
面试中关于图的常见问题
- 实现广度和深度优先搜索
- 检查图是否为树
- 计算图的边数
- 找到两个顶点之间的最短路径
7.散列表 (Hash)
**散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数叫做散列表.
哈希表在应用中也是比较常见的,就如Java中有些集合类就是借鉴了哈希原理构造的,例如HashMap,HashTable等,利用hash表的优势,对于集合的查找元素时非常方便的,然而,因为哈希表是基于数组衍生的数据结构,在添加删除元素方面是比较慢的,所以很多时候需要用到一种数组链表来做,也就是拉链法。
特点:
- 可以利用哈希函数快速访问到数组的目标数据。如果发生哈希冲突,就使用链表进行存储。
- 如果数组的空间太小,使用哈希表的时候就容易发生冲突,线性查找的使用频率也会更高;反过来,如果数组的空间太大,就会出现很多空箱子,造成内存的浪费。因此,给数组设定合适的空间非常重要。
- 在存储数据的过程中,如果发生冲突,可以利用链表在已有数据的后面插入新数据来解决冲突。这种方法被称为“链地址法”。除了链地址法以外,还有几种解决冲突的方法。其中,应用较为广泛的是“开放地址法”。
8.堆 (Heap)
堆是一种图的树形结构,被用于实现“优先队列”(priority queues)。优先队列是一种数据结构,可以自由添加数据,但取出数据时要从最小值开始按顺序取出。在堆的树形结构中,各个顶点被称为“结点”(node),数据就存储在这些结点中。
堆的特点:
- 每个节点最多有两个子节点
- 排列顺序必须从上到下,同一行从左到右
- 堆中某个节点的值总是不大于或不小于其父节点的值;
- 存放数据时,一般会把新数据放在最下面一行靠左的位置。如果最下面一行没有多余空间时,就再往下另起一行,并把数据添加到这一行的最左端。
堆的性质:
- 堆总是一棵完全二叉树
- 堆中某个节点的值总是不大于或不小于其父节点的值
将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。
因为堆有序的特点,一般用来做数组中的排序,称为堆排序。