【数据结构面试常见问题】

preface

数据结构作为计算机的一门基础学科,它在面试中占有很大的比重,本科阶段,我们也学过数据结构与算法,内容比较多,也比较难,尤其是图的应用以及各类查找和排序算法,这些也都是核心内容。数据结构在实际的应用中也比较多,因此,整理一些常见的笔试、面试的数据结构常考点非常有必要,本文将对数据结构常见面试问题进行整理,以便大家查阅。

第一章 绪论

1.数据结构的逻辑结构有哪些?物理结构有哪些?

​ 数据的逻辑结构是指数据元素之间的逻辑关系,即从逻辑关系上描述数据。数据的逻辑结构分为线性结构和非线性结构,线性结构包括一般的线性表、栈、队列、串、数组,非线性结构包括集合、树、图。

​ 数据的物理结构是指数据结构在计算机中的表示(又称映像),也称存储结构。数据的物理结构主要有顺序存储、链式存储、索引存储和散列存储。

2.什么是算法?算法的五大特性是什么?一个好的算法应该具备什么样的条件?

​ 算法是对特定问题求解步骤的一种描述,是指令的有限序列,其中的每条指令表示一个或多个操作。算法的五个特征分别是有穷性、确定性、可行性、输入、输出。一个好的算法应该达到的目标是正确性、可读性、健壮性、效率与低存储量需求。

3.什么是数据结构?数据结构在学什么?

​ 数据结构是相互之间存在一种或多种特定关系的数据元素的集合。数据结构研究的是计算机操作对象的逻辑结构、物理结构以及数据的运算。

4.数据结构的复杂度是什么意思?

时间复杂度:算法中所有语句的频次。

空间复杂度:指算法运行过程中所使用的的辅助空间的大小。

5.常见的数据结构有哪些,说说他们之间的逻辑关系。

数据结构四种常见的逻辑结构:

1)集合:数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系;

2)线性结构:数据结构中的元素存在一对一的相互关系;

3)树形结构:数据结构中的元素存在一对多的相互关系;

4)图形结构:数据结构中的元素存在多对多的相互关系。

第二章 线性表

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

1.顺序表和链表的比较

①存取(读取)方式

​ 顺序表可以顺序存取,也可以随机存取,链表只能从表头顺序存取元素。

②逻辑结构与物理结构

​ 采用顺序存储时,逻辑上相邻的元素,对应的物理存储位置也相邻。而采用链式存储时,逻辑上相邻的元素,物理存储位置不一定相邻,对应的逻辑关系是通过指针链接来实现的。

③查找、插入和删除操作

查找:对于按值查找,顺序表无序时,两者的时间复杂度均为O(n);顺序表有序时,可采用折半查找,此时的时间复杂度为O (log2n)。对于按序号查找,顺序表支持随机访问,时间复杂度仅为O(1),而链表的平均时间复杂度为O(n)。

插入、删除:顺序表的插入、删除操作,平均需要移动半个表长的元素;链表的插入、删除操作,只需要修改相应的结点指针域即 可。由于链表的每个结点都带有指针域,故而存储密度不够大。

④空间分配

顺序存储在静态存储分配情形下,一旦存储空间装满就不能扩充,若再加入新的元素,则会出现内存溢出,因此需要预先分配足够大 的存储空间。预先分配过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。动态分配存储虽然存储空间可以扩 充,但需要移动大量元素,导致操作效率降低,而且若内存中没有更大块的连续存储空间,则会导致分配失败。

链式存储的结点空间只在需要时申请分配,只要内存有空间就可以连续分配,操作灵活、高效。

2.解释下头指针和头结点的区别?单链表增加头结点的目的是什么?

头指针:是指向第一个结点存储位置的指针,具有标识作用,无论链表是否为空,头指针都存在。

头结点:是为了操作统一和方便设立的,放在第一个元素结点之前,头结点的数据域可以不存储任何信息,因此头结点可有可无。

单链表增加头结点可以方便运算。

3.循环链表的优点是什么?

可以从任意一个结点访问整个链表。

4.数组和链表的区别是什么?(比较经典的问题)

​ 从逻辑结构来看:数组的存储长度是固定的,即数组大小定义之后不能改变,而且在插入和删除操作需要移动大量元素,相反对于 链表,它能够动态分配存储空间以适应数据动态增减的情况,并且易于进行插入和删除操作。

​ 从访问方式来看:数组中的元素在内存中连续存放,可以通过数组下标进行随机访问,访问效率比较高。链表是链式存储结构,它 的存储空间不是必须连续,可以是任意的,因此访问链表必须从前往后依次进行,访问效率比较低。

5.解释一下顺序存储和链式存储

​ 顺序存储是用一段连续的存储空间来存储数据元素,可以进行随机访问,访问效率较高。

​ 链式存储是用任意的存储空间来存储数据元素,不能进行随机访问,访问效率较低。

第三章 栈和队列

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

1.请说明栈与队列的区别

​ 首先,栈和队列都是操作受限的线性表,栈只能在表的一端进行插入和删除,队列只能在表的一端进行插入另一端进行删除。

​ 其次,栈是先进后出,队列是先进先出。

2.栈的应用有哪些?

括号匹配、表达式的计算、递归的应用。

括号匹配:遇到左括号就将其压入栈中,遇到右括号就将栈顶的左括号弹出,检查其是否与当前扫描的右括号匹配。

表达式的计算:前缀、后缀表达书:运算符在两个操作数前面、后面。从左往右依次扫描下一个元素,直到处理完所有元素;若扫描 到操作数就将其压入栈中,并继续扫描,若扫描到运算符,则弹出两个栈顶元素,执行相应运算,运算结果压回栈顶,并继续扫描。

递归的应用:每进一层递归,就将递归调用所需要的信息压入栈顶;每退出一层递归,就从栈顶弹出相应信息。

第四章 串

1.介绍一下字符串模式匹配算法:朴素模式匹配算法的KMP算法。

串的模式匹配:在主串中找到与模式串相同的字串,并返回其所在位置。

朴素模式匹配算法:将模式串的字符与主串中的每一个字串一一进行对比。

KMP:指向主串的指针不回溯,依次往后进行匹配比较,而指向模式串的指针需要回溯,当某个位置的字符匹配失败时,模式串指针 根据next数组指向相应的位置,在进行匹配。

第五章 树与二叉树

【数据结构面试常见问题】_第3张图片

1.二叉树与度为2的树有什么区别?

①度为2的树至少有三个结点,而二叉树可以为空。

②度为2 的有序树的孩子的左右次序是相对于另一孩子而言的,若某个结点只有一个孩子,则这个孩子就无需区分其左右次序,而二 叉树无论其孩子数是否为2,均需确定其左右次序,即二叉树的节点次序不是相对于另一结点而言,而是确定的。

2.引入线索二叉树有什么作用?

引入线索二叉树是为了加快查找结点前驱和后继的速度。将二叉树的空链域接入指针,根据二叉树的遍历方式左指针指向直接前驱结 点,右指针指向直接后继结点,以加快查找前驱和后继的速度。

3.如何构造哈夫曼树?哈夫曼编码的意义是什么?

构造哈夫曼树的算法描述如下:

​ 1)将n个结点分别看作n棵仅含一个结点的二叉树。

​ 2)在所有的根节点中选取两个根节点权值最小的数构造成新的二叉树,再将根节点与其他n-1个根节点进行比较,选出根节点 权值最小的两棵树进行归并,重复上述步骤,直至所有结点都归并到一个树上为止。

哈夫曼编码的意义:

​ 将出现频率高的字符使用较短的编码,反之出现频率较低的则使用较长的编码,降低字符串的平均期望长度。频繁使用的机 器指令操作使用较短的编码,这样会提高执行的效率。

4.什么是二叉树?什么是二叉排序树?

​ 二叉树:是一种树形结构,其特点是每个结点至多只有两颗子树,并且二叉树的子树有左右之分,其次序不能任意颠倒。

​ 二叉排序树:是左子树结点值<根节点值<右子树结点值。

​ 平衡二叉树:树上任意结点的左子树和右子树的深度差不超过1.

​ 满二叉树:一颗二叉树的结点要么是叶子结点要么它有两个子节点。

​ 完全二叉树:若设二叉树的深度为h,除第h层外,其他各层节点数都达到最大个数,第h层结点都连续集中在最左边。

​ 最优二叉树:也叫哈夫曼树,树的带权路径长度达到最小,权值较大的结点离根较近。哈夫曼树的特点:没有度数为1的结点,又 称为正则二叉树。n 个叶子节点的哈夫曼树,度数为2的节点数为n-1个,所以哈夫曼树一共有2n-1个节点。

5.为什么要引入平衡二叉树?

平衡二叉树,一定是二叉排序树,之所以将其排序调整为平衡状态,是为了在二叉排序树近似为链的情况下增强其查找性能,降低时 间复杂度。

第六章 图

【数据结构面试常见问题】_第4张图片

1.简述一下广度优先遍历和深度优先遍历

广度优先遍历:首先访问结点v,由近至远依次访问和v邻接的未被访问过的结点,类似于层次遍历。

深度优先遍历:首先访问顶点v,若v的第一个邻接点没有被访问过,则访问该邻接点;若v的第一个邻接点已经被访问,则访问其第 二个邻接点;类似于先序遍历。

2.简述一下求最小生成树的两种算法。

最小生成树:生成树集合中,边的权值之和最小的树。

普利姆(prim)算法:从某一个顶点开始构建生成树,每次将代价最小的新的顶点纳入生成树中,直到所有顶点都纳入为止,适用于 边稠密图。

克鲁斯卡尔(kruskal)算法:按照边权值递增的次序构建生成树,每次选择一条权值最小的边,使这条边的两头连通(原本已连通 就不选),直到所有结点都连通为止,适用于边稀疏图。

3.简述一下求最短路径的两种算法

最短路径:把带权路径长度最短的那条路径称为最短路径。

迪杰斯特拉(Dijkstra)算法:求单源最短路径,用于求某一顶点到其他顶点的最短路径,它的特点是以起点为中心层层向外扩展, 直到扩展到终点为止,迪杰斯特拉算法要求的边权值不能为负。

弗洛伊德(Floyd)算法:求各顶点之间的最短路径,用于解决任意两点间的最短路径,它的特点是可以正确处理有向图或负权值的 最短路径问题。

4.简述一下什么是拓扑排序?

拓扑排序:它是一个有向边无环图,它的思想是选择一个入度为0的顶点并输出,然后删除此顶点以及所有出度,循环直到结束。

5.简述下邻接矩阵与邻接表的区别?

邻接矩阵:矩阵的第i行第j列表示i到j是否连接。

邻接表:链表后面跟着所有指向的点。

邻接矩阵的优点是可以很方便的知道两个节点之间是否存在边,以及快速的添加或删除边;缺点是如果节点个数比较少容易造成存储 空间的浪费。

邻接表的优点是节省空间,只给实际存在的边分配存储空间;缺点是在涉及度时可能需要遍历整个链表。

第七章 查找

【数据结构面试常见问题】_第5张图片

1.谈谈你对散列表的认识

散列表又称哈希表,是一种数据结构,特点是数据元素的关键字与其存储地址直接相关。常用的散列函数的构造方法有:直接定址 法、除留余数法、数字分析法、平方取中法。常见的处理冲突的方法有:开放定址法(线性探测法、平方取中法、再散列法、伪随机 序列法)、拉链法。散列表的查找效率取决于三个因素:散列函数、处理冲突的方法和装填因子。

2.数据结构有哪些查找算法?它们分别适用于什么样的存储结构?

顺序查找:又称线性查找,它对顺序表和链表都是适用的,对于顺序表,可通过数组下标递增的顺序来扫描每个元素;对于链表,可 通过next来依次扫描每个元素。

折半查找:又称二分查找,它仅适用于有序的顺序表。

分块查找:又称索引顺序查找,它将查找表分为了若干子块,块内元素可以无序,但块间元素是有序的。

第八章 排序

1.什么是算法的稳定性?

算法的稳定性是指关键字值相同的元素在排序之后相对位置不改变。算法是否具有稳定性并不能衡量一个算法的优劣,它主要是对算 法的性质进行描述。

2.数据结构有哪些排序算法?说一到两种排序算法的优劣?并比较时间复杂度?

主要的排序算法有:直接插入排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序

直接插入排序(稳定):将未排序序列中的元素插入到前面已排序好的元素中,最好情况时间复杂度为O(n),平均时间复杂度和最 坏情况为O(n^2)

折半插入排序(稳定):设置三个变量low high mid,令mid=(low+high)/2,若a[mid]>key,则令high=mid-1,否则令low=mid+1,直到 low>high时停止循环,对序列中的每个元素做以上处理,找到合适位置将其他元素后移进行插入。他的比较次数为O(nlog2n),但是因 为要后移,因此时间复杂度为O(n^2),空间复杂度为O(1)。 优点是:比较次数大大减少。

冒泡排序(稳定):从后往前或者从前往后两两比较相邻元素,若为逆序,则交换,直到序列比较完为止。优点是:每一趟不仅能找 到一个最大的元素放到序列后面,而且还把其他元素理顺,如果下一趟排序没有发生交换则可以提前结束排序。时间复杂度为O (n^2),空间复杂度为O(1)。

归并排序(稳定):把两个或者两个以上的有序表合并成一个新的有序表。时间复杂度为O(nlog2n),空间复杂度和待排序的元素个 数相同。

快速排序(不稳定):在序列中任意选择一个元素作为枢轴元素,比它大的元素一律向后移动,比它小的元素一律向前移动,形成左 右两个子序列,再把子序列按上述操作进行调整,直到所有的子序列中都只有一个元素时序列即为有序。优点是:每一趟不仅能确定 一个元素,时间效率较高。时间复杂度为O(nlog2n),空间复杂度为O(log2n)

希尔排序(不稳定):先将序列分为若干个子序列,对各子序列进行直接插入排序,等到序列基本有序时再对整个序列进行一次直接 插入排序。优点是:让关键字值小的元素能够很快移动到前面,且序列基本有序时进行直接插入排序时间效率会提升很多,空间复杂 度为O(1),希尔排序仅适用于线性表为顺序存储的情况。

简单选择排序(不稳定):每经过一趟就在无序部分找到一个最小值然后与无序部分的第一个元素交换位置。优点是:实现起来特别 简单,缺点是:每一趟只能确定一个元素的位置,时间效率低。时间复杂度为O(n^2),空间复杂度为O(1)。

堆排序(不稳定):将待排序序列构造成一个堆,输出堆顶元素,堆底元素送入堆顶,调整堆使其具有堆的性质,继续输出堆顶元 素,依次往复,直到只有一个元素。优点是:对大文件效率明显提高,但对小文件效率不明显。时间复杂度为O(nlog2n),空间复杂度 为O(1)。

算法种类 最好情况 平均情况 最坏情况 空间复杂度 是否稳定
直接插入排序 O(n) O(n^2) O(n^2) O(1)
冒泡排序 O(n) O(n^2) O(n^2) O(1)
简单选择排序 O(n^2) O(n^2) O(n^2) O(1)
希尔排序 O(1)
快速排序 O(nlog2n) O(nlog2n) O(n^2) O(nlog2n)
堆排序 O(nlog2n) O(nlog2n) O(nlog2n) O(1)
2路归并排序 O(nlog2n) O(nlog2n) O(nlog2n) O(n)
基数排序 O(d(n+r)) O(d(n+r)) O(d(n+r))

3.循环比递归效率高?

递归和循环两者完全可以互换。不能完全决定性地说循环地效率比递归的效率高。

①递归

优点:代码简洁、清晰,并且容易验证正确性。

缺点:效率较低,递归是有时间和空间消耗的,递归中很多计算都是重复的,从而给性能带来很大的负面影响。

②循环

优点:速度快,结构简单。

缺点:并不能解决所有的问题。有的问题适合使用递归而不是循环。如果使用循环并不困难的话,最好使用循环。

4.概述一下大根堆的构造过程?并说说堆排序的适用场景。

对于第[n/2]个结点为根的子树进行筛选,使得它的根结点大于等于左右子树(小根堆反之),之后向前依次([n/2]-1~1)为根的子树进行筛选,看该结点值是否大于其左右子树结点,若不大于,则将左右子结点中较大者与之交换,交换后可能会破坏下一级堆,于是继续采用上述方法构造下一级的堆,直到以该结点为根的子树构建成堆为止。

堆排序适用于关键字较多的情况,比如在1亿个数中选出前100个最大值。

你可能感兴趣的:(实用指南,面试,数据结构,算法)