数据结构面试常见问题

目录

  • 一、绪论
  • 二、线性表
  • 三、栈和队列
  • 四、串、数组和广义表
  • 五、树和二叉树
  • 六、图
  • 七、查找
  • 八、内部排序

注:部分题目答案来源于网络

一、绪论

1.时间复杂度和空间复杂度的区别是什么?
(1)时间复杂度是对一个算法运行所占用CPU时间多少的量度;
(2)空间复杂度是对一个算法在运行过程中临时占用的存储空间的大小的量度。

2.数据结构的4种逻辑结构各有什么特点?
(1)集合结构:结构中的数据元素之间除了同属于一种类型外,无其他关系。
(2)线性结构:结构中的数据元素之间存在一对一的关系。
(3)树形结构:结构中的数据元素之间存在一对多的关系。
(4)图状结构或网状结构:结构中的数据元素之间存在多对多的关系。

3.数据结构中的存储结构有哪几种?各有什么有优缺点?

顺序存储结构 链式存储结构 索引存储结构 哈希(或散列)存储结构
原理 顺序存储结构是一种物理结构,是按存储单元的顺序依次连续存放逻辑结构中所有结点形成的结构。逻辑上彼此相邻的结点,在存储器上的物理位置也彼此比邻。 链式存储结构的结点是在元素数据存储的同时附加存储一个指针数据。指针的作用是指出该结点逻辑上的后继结点的存储位置。 在存储数据元素信息的同时还建立附加的索引表,存储所有数据元素信息的表称为主数据表,其中每个数据元素有一个关键字和对应的存储地址 根据元素的关键字通过哈希(或散列)函数直接计算出一个值,并将这个值作为该元素的地址
优点 存储效率高,可实现对元素的随机存取 便于数据修改 查找效率高效 查找速度快
缺点 不便于数据修改,对元素的插入或删除操作可能需要移动一系列的元素 存储空间的利用效率低,且不能对元素进行随机存取 需要建立索引表,增加了空间开销 一般只适合要求对数据能够进行快速查找和插入的场合

4.如何在一个数组中找出两个数相加等于一个固定值的所有数对?
(1)方法1:使用暴力穷举法,用到了2层for循环,时间复杂度为O(n2)
(2)方法2:先将数组排序,然后依次取一个数后,在数组中用二分查找,查找sum-val是否存在,如果存在,则找到了一对二元组,它们的和为sum。排序需要O(nlog2n),二分查找需要(log2n),查找n次,所以时间复杂度为O(nlog2n)
(3)方法3:可以用hash表来存储数组中的元素,这样取得一个数后,去判断sum-val在不在数组中,如果在数组中,则找到了一对二元组,它们的和为sum,不过该算法的缺点就是需要用到一个hash表,增加了空间复杂度。

5.什么是数据结构?C语言、数据结构、算法以及程序之间的关系是什么?
(1)数据结构是指所有数据元素以及数据元素之间的关系,可以看作是相互之间存在着某种特定关系的集合,因此可以我们将数据结构看成是带结构的数据元素的集合。此外,在通常情况下,选择合适的数据结构可以带来提高运行效率或者存储效率。
(2)数据结构、算法以及程序之间的关系是:数据结构+算法=程序
算法不一定要求能够在计算机上直接运行,但程序必须要求能在计算机中运行。C语言只是对算法或者数据结构的描述,描述数据结构和算法不局限于C语言,也可以是C++语言和其他的计算机语言甚至也可以用人的自然语言。

6.什么是数据的逻辑结构和存储结构?
(1)数据的逻辑结构指数据元素之间的逻辑关系,它与数据的存储结构无关,是独立于计算机的。
(2)存储结构是指数据结构在计算机中的表示,也称物理结构。

7.程序和软件的区别是什么?
(1)软件是相对于硬件而言的。是一系列按照特定顺序组织的计算机数据和指令的集合。而程序是软件的一个组成部分,是实现软件功能的主要动力之一,它是软件的必要元素。
(2)软件=程序+文档=数据结构+算法+文档

8.简述背包问题
(1)问题描述:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,如何选择才能使得物品的总价格最高。
(2)基本思路:
① 用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程(动态规划中本阶段的状态往往是上一阶段状态和上一阶段决策的结果)便是:f[i][v]=max{ f[i-1][v], f[i-1][v-w[i]]+v[i] }。
② 详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-w[i]的背包中”,此时能获得的最大价值就是f [i-1][v-w[i]]再加上通过放入第i件物品获得的价值v[i]。

9.简述汉若塔问题
(1)问题定义:有三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方,请问至少需要多少次移动,设移动次数为H(n)。
(2)基本思路:利用递归的思想,先将n-1个圆盘放到B上,然后 将最大的圆盘放到C上,最后将n-1个圆盘放到C上。

二、线性表

1.如何确定单链表是一个环?
(1)方法1:快慢指针。首先创建两个指针1和2,同时指向这个链表的头节点。然后开始一个大循环,在循环体中,让指针1每次向下移动一个节点,让指针2每次向下移动两个节点,然后比较两个指针指向的节点是否相同。如果相同,则判断出链表有环,如果不同,则继续下一次循环。此方法也可以用一个更生动的例子来形容:在一个环形跑道上,两个运动员在同一地点起跑,一个运动员速度快,一个运动员速度慢。当两人跑了一段时间,速度快的运动员必然会从速度慢的运动员身后再次追上并超过,原因很简单,因为跑道是环形的。
(2)方法2:穷举遍历。首先从头节点开始,依次遍历单链表的每一个节点。每遍历到一个新节点,就从头节点重新遍历新节点之前的所有节点,用新节点ID和此节点之前所有节点ID依次作比较。如果发现新节点之前的所有节点当中存在相同节点ID,则说明该节点被遍历过两次,链表有环;如果之前的所有节点当中不存在相同的节点,就继续遍历下一个新节点,继续重复刚才的操作。
(3)方法3:哈希表缓存。首先创建一个以节点ID为键的HashSet集合,用来存储曾经遍历过的节点。然后同样是从头节点开始,依次遍历单链表的每一个节点。每遍历到一个新节点,就用新节点和 HashSet集合当中存储的节点作比较,如果发现HashSet当中存在相同节点ID,则说明链表有环,如果HashSet当中不存在相同的节点ID,就把这个新节点ID存入HashSet,之后进入下一节点,继续重复刚才的操作。

2.数组与链表有什么区别?

数组 链表
逻辑结构 数组必须事先定义固定的长度(即元素个数),不能适应数据动态地增减。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。数组中插入、删除数据项时,需要移动其它数据项 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。
内存存储 数组从栈中分配空间, 对于程序员方便快速,但自由度小。 链表从堆中分配空间, 自由度大但申请管理比较麻烦。
适用情况 需要快速查找数据,很少或不插入和删除元素 需要经常插入和删除元素,很少或不查找元素

三、栈和队列

四、串、数组和广义表

1.KMP的主要思想是什么?
在暴力匹配中,每趟匹配失败都是模式后移一位再从头开始比较。而某趟已匹配相等的字符序列是模式的某个前缀,这种频繁的重复比较相当于模式串在不断地进行自我比较,这就是其低效率的根源。因此,可以从分析模式本身的结构着手,如果已匹配相等的前缀序列中有某个后缀正好是模式的前缀,那么就可以将模式向后滑动到与这些相等字符对齐的位置,主串i指针无须回溯,并继续从该位置开始进行比较。而模式向后滑动位数的计算仅与模式本身的结构有关,与主串无关。

五、树和二叉树

1.简述二叉排序树
答:二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),也称二叉搜索树。它或者是一棵空树,或者是具有以下性质的二叉树:
(1)若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
(2)若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
(3)它的左右子树也分别为二叉排序树。

2.简述线索二叉树
答:对于n个结点的二叉树,在二叉链存储结构中有n+1个空链域,利用这些空链域存放在某种遍历次序下该结点的前驱结点和后继结点的指针,这些指针称为线索,加上线索的二叉树称为线索二叉树。

3.二叉树与度为2的树的区别有哪些?
(1)度为2的树中至少有一个结点的度为2(即至少有3个结点),而二叉树没有这种要求,它可以为空。
(2)度为2的有序树的孩子的左右次序是相对于另一孩子而言的,若某个结点只有一个孩子,则这个孩子就无须区分其左右次序,而二叉树无论其孩子数是否为2,均需确定其左右次序,即二叉树的结点次序不是相对于另一结点而言,而是确定的。

4.二叉树的存储结构有哪些?
答:顺序存储结构和链式存储结构。

六、图

1.最小生成树的算法有哪些?说明一下它们的时间复杂度以及各自的特点。

普里姆(Prim)算法 克鲁斯卡尔(Kruskal)算法
思想 Prim算法基于一种贪心的思想,通过局部最优策略,每次将一条边加入所构建的生成树中,加完n-1条边后,保证最后所得的生成树是整体最优的,即最小生成树。 Kruskal算法同样是基于贪心策略,但是它和Prim算法不同的是,在算法过程中它并不维护一个连通的分量,而是将多个连通分量合并到一起得到一颗生成树。
时间复杂度 O(n2) O(e2)
特点 Prim算法的执行时间与图中的边数e无关,所以特别适合用稠密图求最小生成树 Kruskal算法的执行时间仅与图中的边数e有关,所以特别适合用稀疏图求最小生成树

实际运用:城市之间的交通工程造价最优问题就是一个最小生成树问题。

2.最短路径的算法,迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法有什么不同?

迪杰斯特拉(Dijkstra)算法 弗洛伊德(Floyd)算法
思想 Dijkstra算法是典型的最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。 弗洛伊德(Floyd)算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径算法描述如下:a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大;b.对于每一对顶点u和 v,看看是否存在一个顶点w 使得从u到w再到v比己知的路径更短。如果是更新它。
时间复杂度 O(n2) O(n3)
特点 (1)求解的是单源最短路径问题(2)属于贪心算法(3)不能算有负权的图 (4)对图中的每个顶点都使用该算法,就可以得到与Floyd算法相同的效果 (1)求解的是每对顶点之间的最短路径问题(2)属于动态规划 (3)可以算有负权的图 (4)可以通过Dijkstra算法实现

3.图的存储方式有哪些?每一种方式各有什么优缺点?

邻接矩阵表示法 邻接表表示法 十字链表(仅针对有向图) 邻接多重表(仅针对无向图)
优点 直观、简单;适合存储表示稠密图;方便计算任一顶点的度 适合存储表示稀疏图,能节省存储空间;给定一顶点,能很容易地找出它的所有邻边
缺点 不适合表示稀疏图,会浪费较大的存储空间 存储有向图时,所需的存储空间为存储无向图的2倍,比较浪费存储空间

(1)邻接矩阵表示法
(2)邻接表表示法
(3)十字链表(仅针对有向图)
(4)邻接多重表(仅针对无向图)

4.图的深度和广度遍历是什么,工程上有什么实际应用?以及它们的时空复杂度是多少?
(1)图的深度优先搜索(Depth First Search),简称DFS,和树的先序遍历比较类似。它的思如下:
从图中某顶点v出发:
① 访问顶点v;
② 依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
③ 若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

(2)广度优先搜索算法(Breadth First Search),又称为"宽度优先搜索"或"横向优先搜索",简称 BFS。它的思想如下:
广度优先搜索使用队列来实现,整个过程也可以看做一个倒立的树形:
① 把根节点放到队列的末尾。
② 每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把它们放到队列的末尾。并把这个元素记为它下一级元素的前驱。
③ 找到所要找的元素时结束程序。
④ 如果遍历整个树还没有找到,结束程序。
(3)实际运用:
DFS算法:求解迷宫问题时可以搜索从入口到出口的所有迷宫路径、拓扑排序
BFS算法:求解迷宫问题时可以搜索从入口到出口的最短路径、扫雷游戏
(4)BFS算法和DFS 算法在用邻接矩阵和邻接表表示图时,它们的时空复杂度均一样

时间复杂度 空间复杂度
邻接矩阵 O(V2) O(V)
邻接表 O(V+E) O(V)

5.图的遍历和树的遍历有哪些区别?
(1)图的遍历是指从图的某一点出发访问其余顶点,且使得每一个顶点仅仅被访问一次。一般来说,图的遍历有2种,深度优先遍历和广度优先遍历。
(2)树的遍历是指依次对树中每个结点访问一次且仅访问一次。二叉树的3种最重要的遍历方式分别称为前序遍历、中序遍历和后序遍历。此外还有层次遍历等。

6.什么是AOE网?什么是关键路径?什么是关键活动?什么情况下才会有关键路径?
(1)图中入度为0的顶点表示工程的开始事件,出度为0的顶点表示工程的结束时间,那么称这样的有向图为边表示活动的网,即AOE网(Activity On Edge Network)。
(2)在AOE中,从源点到汇点的所有最大路径长度的路径称为关键路径
(3)有向图中入度为0的顶点和出度为0的顶点都仅有一个,分别称为源点和汇点,从源点到汇点的所有路径中,具有最大路径长度的路径称为关键路径。
(4)关键路径上的活动称为关键活动

7.拓扑排序中使用了哪些数据结构?
答:栈、图、数组

七、查找

1.哈希表的特点以及构造哈希函数的方法有哪些?哈希表会不会发生冲突,有哪些解决冲突的办法?散列表的查找效率(平均查找长度)取决于什么?散列表适合存储什么样的数据?
(1)哈希表的特点:访问速度很快、无序、可能会产生碰撞
(2)构造哈希函数的方法:直接定址法、数字分析法、平方取中法、除留余数法
(3)没有完美的散列函数,无论如何总会产生冲突
(4)解决冲突的办法:开放地址法(线性探测法、平方探测法、再散列法、伪随机序列法)、链地址法(也称拉链法)
(5)散列表的查找效率取决于散列函数、处理冲突的方法和装填因子
(6)散列表适合存储需要快速查找且关键字很少重复甚至不重复的数据。

2.B(或称B-)树和B+树的主要区别有哪些?

B树 B+树
具有n个关键字的结点含有n+1棵子树 具有n个关键字的结点只含有n棵子树,即每个关键字对应一棵子树
非叶子结点不仅起索引作用,而且还带信息,所有的叶子结点不带信息(可以视为外部结点或类似看成折半查找判定树的查找失败结点) 叶结点包含信息,所有非叶结点仅起索引作用,非叶结点中的每个索引项只含有对应子树的最大关键字和指向该子树的指针,不含有该关键字对应记录的存储地址
叶结点包含的关键字和其他结点包含的关键字是不重复的 叶结点包含了全部关键字,即在非叶结点中出现的关键字也会出现在叶结点中
非叶结点上的关键字值等于给定值时立即终止 非叶结点上的关键字值等于给定值时并不终止,而是继续向下查找,直到叶结点上的该关键字为止,即无论查找成功与否,每次查找都是一条从根结点到叶结点的路径

八、内部排序

数据结构面试常见问题_第1张图片
数据结构面试常见问题_第2张图片

注:上图中少了一种折半插入排序(属于插入排序):

折半插入排序 O(n) O(n2) O(n2) O(1)

1.排序算法中那些最坏和平均的时间复杂度是一样的?
答:直接插入排序,折半插入排序,冒泡排序,简单选择排序,归并排序,堆排序,基数排序。

2.排序算法中最好和最差的时间复杂度相同的排序算法有哪些?
答:简单选择排序,归并排序,堆排序,基数排序。

3.排序算法中最好、最坏、平均时间复杂度都一样的排序算法有哪些?
答:简单选择排序、堆排序、二路归并排序、基数排序。

4.平均时间复杂度为O(nlog2n) 的排序方法有哪些?
答:快速排序、堆排序、2路归并排序。

5.描述一下快速排序的过程。
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

6.设计一个效率最好的查找。

你可能感兴趣的:(杭电计算机考研,数据结构)