博主本人整理资料不易,如果文章对大家有用的话,恳请大家能够动动小手帮忙点个赞,如果能点个关注的话那就更好了…

文章目录

  • 数组和链表
  • 请你说一下红黑树和AVL树的定义、特点、以及二者的区别
  • 请你说一下哈夫曼编码
  • 请你介绍一下B+树
  • 请说一说你理解的栈溢出,并举个简单例子导致栈溢出
  • 请你回答一下堆和栈的区别,以及为什么栈要快
  • 请说说小根堆特点
  • 请回答一下Array和List,数组和链表的区别
  • 请问求第k大的数的方法及各自的复杂度是怎样的,另外当有相同元素时,还可以使用什么不同的方法求第k大的元素
  • 请你来介绍一下各种排序算法及时间复杂度
  • 请你介绍一下快速排序算法;以及什么是稳定性排序,快速排序是稳定的吗;
  • 请你说一说哈希冲突的解决方法
  • 判断一个链表是否为回文链表,说出你的思路并手写代码
  • 递归的三要素
  • 普利姆算法
  • 克鲁斯卡尔算法
  • 二分查找
  • 冒泡排序

数组和链表

  • 数组
    特点
    1.在内存中,数组是一块连续的区域
    2.数组需要预留空间
    在使用前需要提前申请所占内存的大小,这样不知道需要多大的空间,就预先申请可能会浪费内存空间,即数组空间利用率低
    3.在数组起始位置处,插入数据和删除数据效率低
    4.随机访问效率很高,时间复杂度可以达到O(1)
    5.数组开辟的空间,在不够使用的时候需要扩容,扩容的话,就会涉及到需要把旧数组中的所有元素向新数组中搬移
    6.数组的空间是从栈分配的
    优点:
    随机访问性强,查找速度快,时间复杂度为O(1)
    缺点
    1.头插和头删的效率低,时间复杂度为O(N)
    2.空间利用率不高
    3.内存空间要求高,必须有足够的连续的内存空间
    4.数组空间的大小固定,不能动态拓展
  • 链表:
    特点:
    1.在内存中,元素的空间可以在任意地方,空间是分散的,不需要连续
    2.链表中的元素都会两个属性,一个是元素的值,另一个是指针,此指针标记了下一个元素的地址
    3.查找数据时效率低,时间复杂度为O(N)
    4.空间不需要提前指定大小,是动态申请的,根据需求动态的申请和删除内存空间,扩展方便,故空间的利用率较高
    5.任意位置插入元素和删除元素效率较高,时间复杂度为O(1)
    6.链表的空间是从堆中分配的
    优点:
    1.任意位置插入元素和删除元素的速度快,时间复杂度为O(1)
    2.内存利用率高,不会浪费内存
    3.链表的空间大小不固定,可以动态拓展
    缺点:
    随机访问效率低,时间复杂度为0(N)

请你说一下红黑树和AVL树的定义、特点、以及二者的区别

  • 平衡二叉树(AVL)树:
    平衡二叉树又称AVL树,是一种特殊的二叉排序树。其左右子树都是平衡二叉树,且左右子树高度之差的绝对值不超过1。
    一句话表述为:以树中所有节点为根的树的左右子树高度之差的绝对值不超过1。将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF,那么平衡二叉树上的所有结点的平衡因子只可能是-1、0和1。只要二叉树上有一个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。
  • 红黑树:
    红黑树是一种二叉查找树,但在每个结点增加一个存储位表示节点的颜色,可以是红或黑(非红即黑)。通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍,因此,红黑树是一种弱平衡二叉树,相对于要求严格的AVL树来说,它的旋转次数少,所以对于搜索,插入,删除操作较多的情况下,通常使用红黑树。
    性质:
    (1)每个结点非红即黑
    (2)根节点是黑的
    (3)每个叶结点(叶结点即树尾端NULL指针或NULL结点)都是黑的
    (4)如果一个节点是红色的,则它的子节点必须是黑色的
    (5)对于任意节点而言,其到叶子点树NULL指针的每条路径都包含相同数目的黑节点
  • 区别:
    AVL树是高度平衡的,频繁的插入和删除,会引起频繁的rebalance,导致效率下降;
    红黑树不是高度平衡的,算是一种折中,插入最多两次旋转,删除最多三次旋转。

请你说一下哈夫曼编码

哈夫曼编码是哈夫曼树的一种应用,广泛用于数据文件压缩。哈夫曼编码算法用字符在文件中出现的频率来建立使用0,1表示每个字符的最优表示方式,其具体算法如下:
(1)哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树T。
(2)算法以n个叶节点开始,执行n-1次的合并运算后产生最终所要求的树T。
(3)假设编码字符集中每一个字符c的频率是f(c)。以f为键值的优先队列Q用在贪心选择时有效地确定算法当前要求合并的2棵具有最小频率的树。一旦2棵具有最小频率的树合并后,产生一棵新的树,其频率为合并的2棵树的频率之和,并将新树插入优先队列Q。经过n-1次的合并后,优先队列中只剩下一棵树,即所要求的树T。

请你介绍一下B+树

B+树是一种多路搜索树,主要为磁盘或其他直接存取辅助设备而设计的一种平衡查找树,在B+树中,每个结点都可以有多个孩子,并且按照关键字大小有序排列。所有记录结点都是按照键值的大小顺序存放在同一层的叶节点中。相比B树,其具有以下几个特点:
(1)每个结点上的指针上限为2d而不是2d+1(d为节点的出度)
(2)内节点不存储data,只存储key
(3)叶子节点不存储指针

请说一说你理解的栈溢出,并举个简单例子导致栈溢出

  • 栈溢出的概念:
    栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致栈中与其相邻的变量的值被改变。
  • 栈溢出的原因:
    (1)局部数组过大。当函数内部的数组过大时,有可能导致堆栈溢出。局部变量是存储在栈中的,因此这个很好理解。解决这类问题的办法有两个,一个是增大栈空间,二是改用动态分配,使用堆(heap)而不是栈(stack)。
    (2)递归调用的层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致堆栈溢出。
    (3)指针或数组越界。这种情况最常见,例如进行字符串拷贝,或处理用户输入等等。

请你回答一下堆和栈的区别,以及为什么栈要快

  • 堆和栈的区别:
    (1)扩展方向:堆是由低地址向高地址扩展;栈是由高地址向低地址扩展。
    (2)申请方式:堆由程序员手动分配和管理;栈由系统自动分配和管理;
    (3)效率:堆由程序员分配,速度较慢,分配效率较低,可能由于操作不当产生内存碎片;而栈由系统分配,速度快,分配效率较高,不会有内存碎片。
    (4)程序局部变量使用的是栈空间,new/malloc动态申请的内存是堆空间,函数调用时会进行形参和返回值的压栈出栈,也是用的栈空间。
  • 栈的效率高的原因:
    栈是操作系统提供的数据结构,计算机底层对栈提供了一系列支持:分配专门的存储器存储栈的地址,压栈和入栈有专门的指令执行;
    而堆是由C/C++函数库提供的,机制复杂,需要一系列分配内存、合并内存和释放内存的算法,因此效率较低。

请说说小根堆特点

堆是一棵完全二叉树(如果一共有h层,那么1~h-1层均满,在h层可能会连续缺少若干个右叶子)。

  • 小根堆
    若根节点存在左子女则根节点的值小于左子女的值;若根节点存在右子女则根节点的值小于右子女的值。
  • 大根堆
    若根节点存在左子女则根节点的值大于左子女的值;若根节点存在右子女则根节点的值大于右子女的值。

请回答一下Array和List,数组和链表的区别

  • 数组的特点:
    数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。数组的插入数据和删除数据效率低,插入数据时,这个位置后面的数据在内存中都要向后移。删除数据时,这个数据后面的数据都要往前移动。但数组的随机读取效率很高。因为数组是连续的,知道每一个数据的内存地址,可以直接找到给定地址的数据。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。数组需要预留空间,在使用前要先申请占内存的大小,可能会浪费内存空间。并且数组不利于扩展,数组定义的空间不够时要重新定义数组。
  • 链表的特点:
    链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。不指定大小,扩展方便。链表大小不用定义,数据随意增删。
  • 各自的优缺点
    数组的优点:
    (1)随机访问性强
    (2)查找速度快
    数组的缺点:
    (1)插入和删除效率低
    (2)可能浪费内存
    (3)内存空间要求高,必须有足够的连续内存空间
    (4)数组大小固定,不能动态拓展
    链表的优点:
    (1)插入删除速度快
    (2)内存利用率高,不会浪费内存
    (3)大小没有固定,拓展很灵活
    链表的缺点:
    不能随机查找,必须从第一个开始遍历,查找效率低

请问求第k大的数的方法及各自的复杂度是怎样的,另外当有相同元素时,还可以使用什么不同的方法求第k大的元素

  • 首先使用快速排序算法将数组按照从大到小排序,然后取第k个,其时间复杂度最快为O(nlogn)
  • 使用堆排序,建立最大堆,然后调整堆,直到获得第k个元素,其时间复杂度为O(n+klogn)
  • 首先利用哈希表统计数组中每个元素出现的次数,然后利用计数排序思想,线性从大到小扫描过程中,前面有k-1个数则为第k大的数
  • 利用快速排序思想,从数组中随机选择一个数i,然后将数组分成两部分Dl,Dr,Dl的元素都小于i,Dr的元素都大于i。然后统计Dr元素个数,如果Dr元素个数等于k-1,那么第k大的数即为k,如果Dr元素个数小于k,那么继续求Dl中第k-Dr大的元素;如果Dr元素个数大于k,那么继续求Dr中第k大的元素。
  • 当有相同元素的时候,首先利用哈希表统计数组中每个元素出现的次数,然后利用计数排序思想,线性从大到小扫描过程中,前面有k-1个数则为第k大的数,平均情况下时间复杂度为O(n)

请你来介绍一下各种排序算法及时间复杂度

  • 插入排序
    对于一个待排序数组来说,其初始有序数组个数为1,然后从第二个元素,插入到有序数组中。对于每一次插入操作,从后往前遍历有序数组,如果当前元素大于要插入元素,则后移一位;如果当前元素小于或等于要插入的元素,则将要插入的元素插入到当前元素的下一位中。
  • 希尔排序
    先将整个待排序记录分割成若干子序列,然后分别进行直接插入排序,待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序。其子序列的构成不是简单的逐段分割,而是将每隔某个增量的记录组成一个子序列。希尔排序时间复杂度与增量序列的选取有关,其最后一个值必须为1。
  • 归并排序
    该算法采用分治法;对于包含m个元素的待排序序列,将其看成m个长度为1的子序列。然后两两合归并,得到m/2个长度为2或者1的有序子序列;然后再两两归并,直到得到1个长度为m的有序序列。
  • 冒泡排序
    对于包含n个元素的待排序数组,重复遍历数组,首先比较第一个和第二个元素,若为逆序,则交换元素位置;然后比较第二个和第三个元素,重复上述过程。每次遍历会把当前n-i个元素中的最大的元素移到第n-i位置。遍历n次,完成排序。
  • 快速排序
    通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
  • 选择排序
    每次循环,选择当前无序数组中最小的那个元素,然后将其与无序数组的第一个元素交换位置,从而使有序数组元素加1,无序数组元素减1,初始时无序数组为空。
  • 堆排序
    堆排序是一种选择排序,利用堆这种数据结构来完成。其算法思想是将待排序的数据构造成一个最大堆(升序)/最小堆(降序),然后将堆顶元素与待排序数组的最后一个元素交换位置,此时末尾元素就是最大/最小的值。然后将剩余n-1个元素重新构造成最大堆/最小堆。
  • 各个排序的时间复杂度、空间复杂度及稳定性如下:

请你介绍一下快速排序算法;以及什么是稳定性排序,快速排序是稳定的吗;

  • 快速排序算法
    根据哨兵元素,用两个指针指向待排序数组的首尾,首指针从前往后移动找到比哨兵元素大的,尾指针从后往前移动到比哨兵元素小的,交换两个元素,直到两个指针相遇,这是一趟排序,经过这趟排序后,比哨兵元素大的在右边,小的在左边。经过多趟排序后,整个数组有序。
    稳定性:不稳定
    平均时间复杂度:O(nlogn)
  • 稳定排序
    假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则为不稳定的。
    快速排序算法是不稳定的排序算法。例如:
    待排序数组:int a[ ]={1,2,2,3,4,5,6};
    若选择a[2](即数组中的第二个2)为枢轴,而把大于等于比较字的数均放置在大数数组中,则a[1](即数组中的第一个2)会到pivot的右边,那么数组中的两个2非原序。
    若选择a[1]为比较字,而把小于等于比较字的数均放置在小数数组中,则数组中的两个2顺序也非原序。

请你说一说哈希冲突的解决方法

  • 1、开放定址法
    开放定址法有个非常关键的特征,就是所有输入的元素全部放在哈希表里,也就是说,位桶的实现是不需要任何的链表来实现的,换句话说,也就是说哈希表的装载因子不会超过1。它的实现是在插入一个元素的时候,先通过哈希函数进行判断,若是发生哈希冲突,就以当前地址为基准,根据再寻址的方法(探查序列),去寻找下一个地址,若发生冲突再去寻找,直至找到一个为空的地址为止。所以这种方法又称再散列法。
    有几种常见的探查序列的方法:

    • (1)线性探测
      di=1,2,3,4,5…,m-1;这种方法的特点是:冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。
    • (2)二次探查
      di=1²,-1²,2²,-2²,…,k²,-k²(k<=m/2);这种方法的特点是:冲突发生时,在表的左右进行跳跃式探测,比较灵活。
    • (3)伪随机探测
      di=伪随机数序列;具体实现时,应建立一个伪随机数发生器,如(i=(i+p)%m),生成一个随机序列,并给定一个随机数做起点,每次去加上这个伪随机数++就可以了。
  • 2、链地址法
    每个位桶实现的时候,采用链表或者树的数据结构来存取发生哈希冲突的输入域的关键字,也就是被哈希函数映射到同一个位桶上的关键字。

    紫色部分即代表哈希表,也称哈希数组,数组中的每个元素都是一个单链表的头节点,链表是用来解决冲突的,如果不同的key映射到了数组的同一位置处,就将其放入单链表中,即链接在桶后。
  • 3、公共溢出区
    建立一个公共溢出区域,把hash冲突的元素都放在该溢出区里。查找时,如果发现hash表中对应桶里存在其他元素,还需要在公共溢出区里再次进行查找。
  • 4、再哈希法
    再散列法其实很简单,就是再使用哈希函数去散列一个输入的时候,输出是同一个位置就再次散列,直至不发生冲突位置。
    缺点:每次冲突都要重新散列,计算时间增加。

判断一个链表是否为回文链表,说出你的思路并手写代码

  • 思路
    使用栈存储链表前半部分,然后一个个出栈,与后半部分元素比较,如果链表长度未知,可以使用快慢指针的方法,将慢指针指向的元素入栈,然后如果快指针指向了链表尾部,此时慢指针指向了链表中间

递归的三要素

1). 明确递归终止条件

我们知道,递归就是有去有回,既然这样,那么必然应该有一个明确的临界点,程序一旦到达了这个临界点,就不用继续往下递去而是开始实实在在的归来。换句话说,该临界点就是一种简单情境,可以防止无限递归。

2). 给出递归终止时的处理办法

我们刚刚说到,在递归的临界点存在一种简单情境,在这种简单情境下,我们应该直接给出问题的解决方案。一般地,在这种情境下,问题的解决方案是直观的、容易的。

3). 提取重复的逻辑,缩小问题规模

我们在阐述递归思想内涵时谈到,递归问题必须可以分解为若干个规模较小、与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决。从程序实现的角度而言,我们需要抽象出一个干净利落的重复的逻辑,以便使用相同的方式解决子问题。

普利姆算法

Prime算法的核心步骤
在带权连通图中V是包含所有顶点的集合, U已经在最小生成树中的节点,从图中任意某一顶点v开始,此时集合U={v},重复执行下述操作:在所有u∈U,w∈V-U的边(u,w)∈E中找到一条权值最小的边,将(u,w)这条边加入到已找到边的集合,并且将点w加入到集合U中,当U=V时,就找到了这颗最小生成树。

克鲁斯卡尔算法

(1)设一个有n个顶点的连通网络为G(V,E),最初先构造一个只有n个顶点,没有边的非连通图T={V,空},图中每个顶点自成一格连通分量。
(2)在E中选择一条具有最小权植的边时,若该边的两个顶点落在不同的连通分量上,则将此边加入到T中;否则,即这条边的两个顶点落到同一连通分量 上,则将此边舍去(此后永不选用这条边),重新选择一条权植最小的边。
(3)如此重复下去,直到所有顶点在同一连通分量上为止。

二分查找

定义left为顺序表最左端元素位置,right为顺序表右端元素位置。定义mid = (left + right) / 2,即顺序表的中间位置,然后用所查找的值与mid所在位置处的值比较,由于列表有序,若所查找的值比mid小,则只需在表的前半部分查找,否则只需在表的后半部分查找(若第一次比较就发现两值相等则直接返回当前值所在的位置),以此类推,直至查找到所寻找的值或确定所查找的值不在该列表内为止(即查找失败)。

冒泡排序

原理:从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。
以从小到大排序为例,第一轮比较后,所有数中最大的那个数就会浮到最右边;第二轮比较后,所有数中第二大的那个数就会浮到倒数第二个位置……就这样一轮一轮地比较,最后实现从小到大排序。

计算机考研复试之数据结构相关推荐

  1. 武汉大学计算机考研 专业课程,2018武汉大学计算机考研复试经验贴

    2018武汉大学计算机考研复试经验贴 武汉大学 发布于2019年9月22日 12:25 阅读数 18196 初试唯一要讲的就是专业课问题,今年专业课改革,只考两门专业课.一门是数据结构,分值为90分, ...

  2. 计算机考研复试面试常问问题 数据库篇

    计算机考研复试面试常问问题 数据库篇 在复习过程中,我用心查阅并整理了在考研复试面试中可能问到的大部分问题,并分点整理了答案,可以直接理解背诵并加上自己的语言润色!极力推荐打印下来看,效率更高!绝对良 ...

  3. 计算机考研复试面试常问问题 编程语言篇

    计算机考研复试面试常问问题 编程语言篇 个人整理,免费分享,不可用于商业用途,转载请注明出处! 但是有同学反应闲鱼上有人盗卖此免费分享资料,还有好多同学买了,所以希望大家多多点赞评论收藏,提高这份资料 ...

  4. 2021武汉理工大学计算机考研复试经验分享(最新版)

    2021武汉理工大学计算机考研复试经验分享 简介    最近,刚刚结束了期末考试回家,也是陆陆续续接到群里面的很多好友询问一些关于复试的要求和准备方法.最近我也是将以前复试的资料和我当时做的一些准备工 ...

  5. 2022年华南理工大学计算机考研复试时间

    2022年华南理工大学计算机考研复试在几月份呢?2022年华南理工大学计算机考研初试已于2021年12月结束,现已进入2022年,迎接计算机考研党的是考研初试成绩.复试分数线以及复试时间,接下来就由小 ...

  6. 南京理工大学计算机考研2020复试和录取,南京理工大学计算机考研复试科目

    南京理工大学计算机考研复试科目如下~ 复试形式: 笔试(100分)+面试(80分)+机试(120分). 面试:考核英语交流水平(30分).专业素质.综合能力等. 各专业笔试如下: 计算机系统结构.计算 ...

  7. 计算机考研复试--英语常问问题及答案

    计算机考研复试–英语常问问题及答案 Category 1: Personal Questions Question 1.1: Tell us something about yourself. Ans ...

  8. 计算机考研复试C语言最强简单题资料

    计算机考研复试C语言最强简答题资料 什么是C语言? C语言是一门面向过程.抽象化的通用程序设计语言,广泛应用于底层开发.C语言能以简易的方式编译.处理低级存储器.尽管C语言提供了许多低级处理的功能,但 ...

  9. 河海大学20计算机考研复试回忆

    河海大学20计算机考研复试回忆 2020年真的是很特殊的一年,全国上下共同奋战抵抗疫情,最终取得了阶段性胜利,距离完全胜利可能还需要点时间.与此同时,以考研为首的各种重要考试也不得不延期或转变考试方式 ...

最新文章

  1. Pause/Resume Instance 操作详解 - 每天5分钟玩转 OpenStack(34)
  2. Kafka本身的架构
  3. 简单实现KeyChain实例
  4. 黑客魔术!如何黑掉一台根本不联网的电脑
  5. vnr懒人版教程_凉皮懒人做法,不揉面不洗面,配方配料无保留,简单快速又好吃...
  6. [转]ETL模型设计
  7. jQuery表格排序组件-tablesorter
  8. 超好用的开源 IP 地址管理系统,告别传统 Excel 统计方式!
  9. MySQL单元三试题与答案_2016年3月三级MySQL数据库试题及答案
  10. 【科研小技巧|知网】如何下载 PDF 格式的学位论文
  11. 服务器安装macos虚拟机,Win10虚拟机VMware安装黑苹果MacOS Sierra图文教程
  12. Zephry Uart Device详解
  13. 惠普服务器如何插内存
  14. 阿里云 杭州 ARM 云服务器性能评测
  15. python开源项目贡献_为开源项目做出第一笔贡献
  16. Android 沉浸式(透明)状态栏细研-超级细还附 Demo
  17. 思维模型 六顶思考帽
  18. HYSBZ 2565 最长双回文串 (回文树)
  19. 符合这8种性格的人都长寿
  20. 搜狗 workflow异步调度框架--1.基本介绍篇

热门文章

  1. android 商城常用控件,android 自定义商城app价格正序倒序控件
  2. 全球企业研发投入排行榜:苹果第七,华为第五,第一是?
  3. ssm项目整合与功能开发(注解开发)
  4. 2022-2027年中国私募股权投资行业发展前景及投资战略咨询报告
  5. 分享一个查询快递物流单号的方法
  6. Android开发整理
  7. 20国外国人被惊呆!直呼这些东西是中国新四大发明!
  8. js判断鼠标滚动放下,向上滚还是向下滚?
  9. PTA团体天梯赛汇总
  10. Xshell入门必看