数据结构-考研复试准备

 💡 一、简述背包问题?

背包问题是动态规划的问题之一,核心思想是记忆化每步决策的最优解。

常见问题有01背包、完全背包和多重背包。

01背包是指给定n件物品,每种物品只有一件,已知每件物品的体积和价值,在背包容量m的范围内求得最大价值和。

通常使用二维数组和滚动数组两种方式解决。

关键是确定dp含义,dp状态转移方程,dp初始化和遍历顺序。

二维数组方法下,dp【i】【j】是指在【0,i】物品范围,容量为j时的最大价值和。

状态转移方程考虑第i件物品是否放入背包中。

M[i][j] = max(M[i-1][j], M[i-1][j-weight[j]] + value[j])

// 初始化 dp
vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));
for (int j = weight[0]; j <= bagweight; j++) {
    dp[0][j] = value[0];
}

滚动数组使用逆向枚举,解决每种物品只有一个的问题。

完全背包是指每种物品不限量,解决办法是利用滚动数组正向枚举。

多重背包是指定每种物品的有限量,解决办法是拉伸到01背包,用二维数组方法解决。

背包问题常用来解决 分割等和子集等问题。

💡 二、java和C++的区别

第一,java支持自动回收不再被使用的对象,释放内存空间。而C++需要调用delete销毁对象。

第二,java不支持数据类型隐式转换,会提示报错。C++支持。C++也可以用其他基本数据类型作为类似bool变量的判断条件,java不可以。

第三,C++有预编译阶段,即预处理器。java没有,但是java的import功能十分相似。

第四,java有异常处理机制,用try catch捕获异常时间,增加系统的容错能力。而C++没有。

第五,java不支持编程人员通过指针直接访问内存位置,防止C++中指针操作失误,如野指针造成系统崩溃,有利于维护java程序安全。

第六,java常用来进行web应用,可移植性好,复用性强。而C++可以直接编译成exe文件,常用于上层应用程序开发,如游戏,多媒体。

💡 三、排序算法有哪些及其时间复杂度

数据量比较大时,使用到磁盘等外存,称为外部排序;

而全部数据记录都存储在内存中,成为内部排序。

先说排序结果稳定的算法

最好最坏平均空间
冒泡排序nn2n21
插入排序nn2n21
归并排序nlognnlognnlognlogn
基数排序nknknkn+k
桶排序nnnN+M
计数排序n+k,k是数据范围n+kn+kn+k

再说排序结果不稳定的算法

最好最坏平均空间
选择排序n2n2n21
快速排序nlognn2nlognlogn
堆排序nlognnlognnlogn1
希尔排序nn2n1.31

💡 排序最优和最差相同的排序算法

选择排序、堆排序、归并排序、基数排序

💡 最差和平均一样的时间复杂度

选择排序、堆排序、归并排序、基数排序、冒泡排序、插入排序

💡 最好最坏平均都一样的排序算法

选择排序、堆排序、归并排序、桶排序、基数排序

💡 四、线性存储和链式存储的优缺点比较

在数据运算方面,线性存储可随机存储,按序号直接访问元素值,而链式存储在该操作时间复杂度为O(n) 。但是线性存储插入、删除元素时,需要移动大量数据,操作麻烦,所以频繁做插入、删除操作时采用链式存储,较方便。

在存储空间方面呢,线性存储需要预先分配空间,过小会造成数据溢出,过大造成空间浪费。而链式存储无需预先分配。但是链式存储在存储结点时,除了当前元素值,还需要额外空间来存储下一单元的内存地址,相对来说,存储密度较低。

在应用环境上,所有的高级语言都有数组类型,所以线性存储更容易实现。

💡 数据结构的存储结构?和对应的存储模式?

存储结构分为4类:

一是线性存储,逻辑上相邻的物理上也相邻;

二是链式存储,逻辑上相邻的物理上不一定相邻;

三是索引存储,需要额外的索引表,类似于文件系统中的目录

四是散列存储,又称哈希存储,根据关键字计算得到元素值

存储模式也分为4类:

集合结构:元素之间除了同属于一种数据类型外,无其他额外关系;

线性结构:元素之间一对一的关系;

树形结构:元素之间一对多的关系;

图形结构:元素之间多对多的关系。

💡 五、hash函数的特点以及如何处理冲突

hash函数的特点是:

第一是,输入域无限,输出域有限。

第二是,不同的输入,可能有相同的输出。

第三是,同一个数据输入,得到的输出元素一样。

第四是,函数易于计算,得到的结果分布均匀。

处理冲突的常用方法有4类:

一是开放地址法,比如线性探测再散列,顺序查找下一个存储单元;二次探测再散列;伪随机数法

二是再散列法,换个哈希函数

三是拉链法,使用链表结点

四是建立公共溢出区,存放出现冲突的关键字记录。

💡 散列表的建立方法?

常见的hash函数有,数字分析法、平方取中法、除留余数法、随机数法、直接寻址法(一种线性关系,运算简单)等。

💡 hash适合存储什么样的数据?

无序但要快速访问的数据

💡 影响hash表平均查找长度的因子

hash函数,装填因子,解决hash冲突的方案

💡 六、最小生成树两种算法优缺点比较

Prim算法是依赖于点的算法,时间和空间复杂度都为O(n2),思想较难理解,常采用邻接矩阵方式实现,适合稠密图。

Kruskal算法依赖于边,思想简单,模板代码量少,时间复杂度为O(eloge)e为网中边数,适合稀疏图。

💡 七、简述以下线索二叉树

因为二叉链表中,只能得到结点的左右孩子,不能得到该节点在遍历序列中的前驱和后继结点。又考虑到n个结点的二叉树有n+1个空指针域。

考虑将空指针域在先序/中序或者后序遍历过程中修改为指向前驱或者后继结点的指针,也就是线索化,最终得到了线索二叉树。

线索二叉树在二叉链表上又增加了两个标志域,LTag和RTag。当LTag为0时,左指针指针指向左孩子,为1时,指向前驱结点。

此外,考虑增加一个头节点,使得像双向链表一样,既可以正向遍历,也可以逆向遍历。

💡 八、怎么确定是一个环

有两种方法,

一种是深度优先搜索时遇到已经访问过的结点,则存在环;

二是拓扑排序过程中不存在无前驱的结点,则存在环。

💡 九、汉诺塔

经典汉诺塔问题表述为:有3根柱子,从左到右序号依次为A\B\C。其中A柱上有n个从小到大的圆盘,求问这些圆盘移动到C柱需要多少次数?要求一次只能移动一个圆盘,小盘不允许放到大盘下面。

这属于递归问题,解题思路为先把上面的n-1个圆盘移动至B盘,再把最大的圆盘放到C,最后把n-1个圆盘放到C柱上,由此得到了递归函数 f(n) = 2(f-1) +1;

类似的,可以再增加条件,允许两侧柱子上的圆盘直接移动,只能借助中间柱子;或者说,允许最大的圆盘放在其余圆盘的上面等。思路都是会考虑n-1圆盘怎么移动,寻找递归函数。

💡 十、图的存储

有四种方式:

一是邻接矩阵,采用二维数组记录边信息;

二是邻接表,使用链式存储和顺序存储;

三是十字链表法,仅针对有向图;

四是邻接多重表,仅针对有向图。

 💡 十一、图的遍历

💡 图的深度和广度遍历是什么?在工程中有哪些应用?

图的遍历是从某一结点出发,对图中所有结点有且只访问一次。

分为深度优先遍历DFS和广度优先遍历BFS,两者的时间复杂度都为O(v+e)

DFS可借助栈或者递归。一句话描述是“一条路往下走,走不通回头,换条路再走,直到无路可走”。

选择某一结点v,执行以下步骤

第一步,访问当前结点v,并标记为已访问。

第二步,查找v结点是否存在与之相邻且未被访问过的结点u,若存在,则将u设置为当前结点,调转至第一步,否则当前结点回退。

BFS借助队列。按层遍历,选择某一结点v,标记为已访问,并放入队列中。

接下来,队列队头出一个元素,并把与之相邻的所有未被访问过的结点放入队列中,都标记为已访问。重复该步骤。

应用有:寻找最短路径,判断是否有环,遍历解答树求解。(解答树是在问题求解时,所有可能的解构成了一个树,满足条件的解就是该数的一个路径或者结点)

💡 树和图的遍历的区别,存储方式

树的先序遍历类似于图的深度优先搜索遍历;树的层次遍历类似于图的广度优先搜索遍历。

相同的地方都是从一个结点出发访问其相邻的结点,树是左右孩子,图是连通的结点。

不同点是对图来说,相邻结点有多个,而树最多只有两个。

而且图遍历时需要一个一维数组,记录已访问过的结点。

树的存储方式有三种:

一是双亲表示法,此时结点存储包括结点值和双亲结点值两部分

二是孩子表示法,该方法实现分为两部分,一是存储结点值和指向第一个孩子结点的地址,二是由指针链组成的其他孩子结点;

三是孩子兄弟表示法,此时结点存储包括,当前节点的第一个孩子结点、结点值、以及兄弟结点。

 💡 十二、两个最短路径算法有什么不同?用于什么情况?

Dijsktra算法(迪杰斯特拉)基于贪心算法,核心思想是从源点出发,找到与源点距离最近的一个顶点,再以此顶点为中心向外进行扩展,最终得到源点到其他路径的最短距离。

Flyod算法(弗洛伊德)基于动态规划,核心思想是顶点u到顶点v之间的最短距离可能是直接连接,也可能经过了若干结点。所以利用三重循环实现算法。

在应用情况上,

首先Dijsktra不能用于距离为负权值的图,否则无法更新数据,Flyod可以。

第二Dijsktra只用于单源最短路,不能用于任意两个结点求解,而Flyod可以。

💡 十三、拓扑排序中使用了哪些数据结构?

用邻接矩阵或者邻接表存储的图、可能也用到栈

 💡 十四、简述二叉排序树

二叉排序树是一颗空树,或者具有以下特性的非空二叉树:

左子树所有结点值小于根节点值、右子树所有结点值大于根结点值、每个子树也是二叉排序树。

当按照递归中序遍历时,得到一个递增序列。

二叉排序树的查找、插入、删除都是从根结点出发,比较大小,逐层遍历,找到合适的位置。其中,删除操作可能会重新链接二叉排序树。而二叉排序树的平均查找长度与树的高度有关。

 💡 十五、二叉树和度为二的树的区别

首先,度为2的树至少一个结点有两个子树,且每节点的子树个数最多为2,而二叉树的子树数量可为1可为0可为2。

其次,度为2的树中结点的两子树无左右区分,而二叉树有左右之分,次序不能颠倒。

💡 十六、程序和软件的区别

软件=程序+文档=数据结构+算法+文档

软件是包含程序的有机集合体,程序是软件的必要元素,软件中至少包括一个可运行的程序。

💡 十七、解释下关键路径和关键活动,什么情况下才有关键路径

AOV网中,顶点表示事件,弧表示活动。路径上各个活动所持续的时间之和成为路径长度。

而从源点到汇点之间的所有路径中,有最大路径长度的路径成为关键路径。

关键路径上的活动成为关键活动。

先算事件的最早发生时间和最迟发生时间,再算活动的最早发生时间和最迟发生时间,

求得存在活动时间余量为0的活动,也就是该活动拖延时间的话,会延长整个工期。

所有余量为0的边连起来就是关键路径。

💡 十八、算法

算法是计算机解决问题的方法、步骤,是解决待定问题求解步骤的描述。

算法有5个特点:输入、输出、有穷性、确定性、可行性。

 💡 十九、B树和B+树的主要区别有哪些?

B树 具有n个关键字的结点含有n+1棵子树;

非叶子结点不仅起索引作用,而且还带信息,所有的叶子结点不带信息(可以视为外部结点或类似看成折半查找判定树的查找失败结点);

叶结点包含的关键字和其他结点包含的关键字是不重复的;

叶结点包含的关键字和其他结点包含的关键字是不重复的。

B+树

具有n个关键字的结点只含有n棵子树,即每个关键字对应一棵子树;

叶结点包含信息,所有非叶结点仅起索引作用,非叶结点中的每个索引项只含有对应子树的最大关键字和指向该子树的指针,不含有该关键字对应记录的存储地址;

叶结点包含了全部关键字,即在非叶结点中出现的关键字也会出现在叶结点中;

非叶结点上的关键字值等于给定值时并不终止,而是继续向下查找,直到叶结点上的该关键字为止,即无论查找成功与否,每次查找都是一条从根结点到叶结点的路径。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值