数据结构关键路径_复试备考的笔试资料(c与数据结构篇)

1.c++怎么压缩数据:

有损压缩:图像或音频的处理。有一定程度偏差和失真,但是没多大影响

无损压缩:最小冗余编码(哈夫曼编码),基于字典的方法。解码前后数据完全一致,没有任何失真和偏差。

哈夫曼编码(不定长编码):哈夫曼编码是无损压缩当中最好的方法(贪心算法),其压缩率通常在20%~90%之间。它使用预先二进制描述来替换每个符号,长度由特殊符号出现的频率决定。常见的符号需要很少的位来表示,而不常见的符号需要很多位来表示。

前缀码:对每一个字符规定一个0,1串作为其代码,并要求任一字符的代码都不是其他字符代码的前缀。

C++压缩编码的两种无损压缩:

5

1 3 4 2 5

33

哈夫曼编码(贪心算法)

1f3463a8bb1c913eb2a1ae45b47872f4.png

计算总长度的方法是每次汇集两个节点,都要加上该节点下所有叶子节点的权重。因为编码规则是贪心策略,即每次汇集两个最小权重的节点,所以会导致编码后的节点序列变化,编码后的序列是ADBCE。

4e026c002f29a77164eb8be6c5715e93.png

基于字典编码(动态规划)

5

1 3 4 2 5

34

a8e64fc3db787ec446e44f2793b19bef.png

而字典序编码则要求编码过程中节点顺序不能改变,也就是每次只能合并相邻的两个节点,并且还要取最小值,同样每次汇集两个节点,都要加上该节点下所有叶子节点的权重。用dp[i][j]表示第i个数到第j个数编码后的最小长度,初始化i==j时dp[i][j]为0,用sum[k]表示前k个数的和,sum[k]-sum[t-1]表示第t到第k个数的和。

状态转移方程为:dp[i][j] = min(dp[i][k]+dp[k+1][j] + sum[j]-sum[i-1])(i<=k<=j)

意思是要将第i到第j个数合并成一个,由于字典序只能合并相邻的,所以只能先合并成i到k,k+1到j两个,再将i到k和k+1到j合并成一个。为了得到最优解,需要把每种可能取值的k都找一遍,取最小值。

2.数据结构能做什么?操作系统中运用的数据结构?深度优先与广度优先的区别?分析一下冒泡排序的时空复杂度。队列,链表

数据结构能做什么?

程序=数据结构+算法

数据结构能做什么:在计算机中,我们到底该怎样存储数据?

算法:怎么样操作这些存储的数据

如果给你很多很多书,让你把书放到图书馆的各个书架上,你会怎么放?在考虑新书入库和已有书查询的操作便捷度的情况下,你对书本的放置方式和操作方式就是所谓的数据结构。从这里不难发现,数据结构实际上是将计算机语言和实际生活进行联系的起点,他教会你如何将实际问题转换成计算机能理解的表达方式,教会你如何使用计算机思维,其非常重要的一个作用就是从思想上将你训练成一个程序员该有的思维模式,而这个过程,非常重要、不可或缺。

图:比如去旅游,那么走的旅游路线(抽象为连通图)

比如你从家要到学校有好多条路,怎么走最节省时间(最短路径问题)

栈:函数递归,括号匹配问题(当前字符若为 ( [ { 如果是的话就压入栈中当前字符若为)] } 的话就判断栈顶元素是否为相对应的括弧),物流装车应用(最先被装到车上的货物最后才能取出来)。

队列:进程/作业调度算法(先来先服务),页面置换算法(先来先服务)歌曲的播放列表

学了队列之后,你就知道,对于先入先出要排队的问题,你就要用到队列,例如多个网络下载任务,我该怎么去调度它们去获得网络资源呢?再例如操作系统的进程(or线程)调度,我该怎么去分配资源(像CPU)给多个任务呢?肯定不能全部一起拥有的,资源只有一个,那就要排队!那么怎么排队呢?用普通的队列?但是对于那些优先级高的线程怎么办?那也太共产主义了吧,这时,你就会想到了优先队列,优先队列怎么实现?用堆,然后你就有疑问了,堆是啥玩意?自己查吧,敲累了。

操作系统中运用的数据结构?

链表:

进程管理-PCB的连接

外存分配方式-链接分配

队列:

进程通信-消息队列的实现

处理机调度-任务就绪列队的实现

存储器管理-Clock置换算法的实现(循环队列)

栈:

存储器管理-LRU(Least Recently used)置换算法

树:

进程管理-进程家族关系描述:进程树

散列表:

内存管理-连续分配方式:Hash算法

文件管理-hash文件

深度优先与广度优先的区别?

二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。图的深度遍历是否唯一?不一定是不唯一。我们可以取图中任一顶点进行深度遍历。深度优先搜索形成的是什么?森林唯一么? (森林,不能说树)(不唯一,因为邻接表可能不唯一)

  • 深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历、中序遍历、后序遍历。【首先访问出发点V,并将其标记为已访问;然后选取与V邻接的未被访问的邻接顶点W,访问 W;再选取与W邻接的未被访问的顶点访问,以此类推。当一个顶点所有的邻接顶点都被访问过时,则依次退回最近被访问过的顶点,若该顶点还有其他邻接顶点未被访问,则从这些顶点中去一个顶点进行上述的过程,直至图中所有顶点都被访问过为止】
  • 广度优先遍历:又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止。【首先访问起始顶点 V,然后选取与 V 邻接的全部顶点 w1,w2,….,wn 进行访问,再依次访问与w1,w2,… ,wn邻接的全部顶点(不包括已访问过的顶点),以此类推,直至所有顶点都被访问过为止】   

分析一下冒泡排序的时空复杂度。

for (i = length-1; i > 0; i--){//n-1趟排序

for (j = 0; j < i; j++){ // 第i个元素进行i次比较

if (array[j] > array[j+1]){// 交换相邻的两个元素,把大的元素交换到后面

tmp = array[j];

array[j] = array[j+1];

array[j+1] = tmp;

}

}

}

3.时间复杂度: 时间复杂度是指执行算法所需要的计算工作量,因为整个算法的执行时间与基本操作重复执行的次数成正比,所以将算法中基本操作的次数作为算法时间复杂度的度量,一般情况下,按照基本操作次数最多的输入来计算时间复杂度,并且多数情况下我们去最深层循环内的语句所描述的操作作为基本操作。

4. 什么是二叉排序树?以及它的原理,算法。(二叉排序树的查找过程) 二叉排序树又称二叉查找树,它或者是一颗空树,或者满足一下性质的二叉树: ① 若左子树不空,则左子树上所有结点的值均小于根节点的值; ② 若右子树不空,则右子树上所有结点的值均大于根节点的值; ③ 左右子树也分别是二叉排序树。 原理步骤:若根结点的关键字值等于查找的关键字,成功。 否则,若小于根结点的关键字值,递归查左子树。 若大于根结点的关键字值,递归查右子树。 若子树为空,查找不成功。【二叉查找树查找的时间复杂度(Olog2n~On)以及中序遍历后得到什么样的序列(递增有序序列)】

平衡二叉树 平衡二叉树又称AVL树,是一种特殊的二叉排序树,其左右子树都是平衡二叉树,且左右子树的高度差的绝对值不超过1. 平衡因子: 左子树高度减去右子树高度的差。 平衡调整: 先找到失去平衡的最小子树,即以距离插入结点最近,且平衡因子绝对值大于 1 的结点作为根节点的子树,分为LL,LR,RL,RR四中调节方式。

5. 哈夫曼树 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树.构造方法: 假设有 n 个权值,则构造出的哈夫曼树有 n 个叶子结点。 n 个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为: (1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点); (2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和; (3)从森林中删除选取的两棵树,并将新树加入森林; (4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。 特点: ① 权值越大的结点,距离根节点越近; ② 树中没有度为一的结点。 应用:哈夫曼编码,减少编码的长度。哈夫曼编码就是长度最短的前缀编码。

6. 什么是哈希冲突?以及如何解决。 散列(哈希)表:根据关键码值(Key value)而直接进行访问的数据结构。根据给定的关键字来计算出关键字在表中的地址,以加快查找的速度。

冲突:指的是多个关键字映射同一个地址的情况。 解决办法:(1)开放定址法 ① 线性探查法(产生堆积问题); ② 平方探查法(不能探查到哈希表上所有的地址,但至少能探查到一半的地址)(2) 链地址法:把所有的同义词用单链表连接起来(不存在堆积问题)。

补充(常见的哈希函数构造方法) 直接定址法,数字分析法,平方取中法,除留余数法。

7. 迪杰斯特拉算法的过程 该算法可以求得某一顶点到其余各顶点的最短路径。 算法思想:设有两个顶点集合S和T,其中集合 S 中存放的是图中已找到最短路径的顶点,集合T中存放的是图中的剩余顶点。 初始状态时,集合S中只包含源点V0,然后不断从集合T中选取到顶点V0路径最短的顶点Vu并加入集合S中。集合S每加入一个新的顶点Vu,都要修改V0到集合T中各个顶点的最短路径的长度值。不断重复这个过程,直至集合T中的顶点全部并入到S中为止。

Floyd和迪杰斯特拉Dijkstra算法有什么区别?

  • Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法的时间复杂度为O(N^2)。
  • Floyd算法是解决任意两点间的最短路径的一种多源最短路径算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd算法的时间复杂度为O(N^3)。

8. 链表查找某个元素,平均的时间复杂度是多少? O(n) 链表是顺序存储,故(1+n)/2。

9. 图的存储方式 ① 邻接矩阵:是图的顺序存储结构,用两个数组分别存储数据元素(顶点)信息和数据元素之间的关系(边/弧)的信息。图的邻接矩阵表示是唯一的,无向图的邻接矩阵是对称的。 ② 邻接表:是图的链式存储结构,由单链表的表头形成的顶点表和单链表其余结点所形成的边表两部分组成。 ③十字链表:有向图的另一种链式存储结构。 ④ 邻接多重表:无向图的链式存储结构。

10. 图的相关概念 图:由结点的有穷集合V和边的集合E组成。 类别:有向图和无向图。 顶点的度:出度和入度。 有向完全图和无向完全图: 若有向图有n个顶点,则最多有n(n-1)条边,则称为有向完全图; 若无向图有n个顶点,则最多有n(n-1)/2条边,则称为无向完全图。 路径:相邻顶点序偶所构成的序列。 简单路径:序列中的顶点和路径不重复出现的路径。 回路:路径中第一个顶点和最后一个顶点相同的路径。 连通: 无向图中,如果Vi到Vj有路径,则称这两个顶点连通。如果图中任意两个顶点之间都连通,则称该图为连通图。 有向图中,如果Vi到Vj有路径,则称这两个顶点连通。如果图中每一对顶点Vi和Vj,从 Vi到 Vj和Vj到Vi都有路径,则称该图为强连通图。【什么图可以进行拓扑排序? 有向无环图 】

11. 最小生成树的概念 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图联通的最少的边。如果在最小生成树中添加一条边,必定成一个环。 相关算法: ① 普里姆算法 ② 克鲁斯卡尔算法 【在有权值相同的边时画出的树可能不同】N个结点的最小生成树有几个结点,几条边:n个结点,n-1 条边。

12. 二叉树的存储 ① 顺序存储结构:用一个数组来存储一颗二叉树,二叉树中的结点值按照编号依次存入一个一维数组中。适用于完全二叉树,若用于一般的二叉树则会浪费大量存储空间。 ② 链式存储结构:二叉树中的每一个结点用一个链结点来存放。

完全二叉树 若一棵二叉树至多只有最下面的两层上的结点的度数可以小于 2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树。 完全二叉树特点: 叶子结点只可能在最大的两层上出现, 对任意结点, 若其右分支下的子孙最大层次为L,则其左分支下的子孙的最大层次必为L 或 L+1; 【满二叉树的结点个数(n层) 2的n次方减一(2n-1) 】

什么是堆?有什么作用? 堆是一种数据结构,可以把堆看成一个完全二叉树,并且这个完全二叉树满足: 任何一个非叶节点的值都不大于(或不小于)其左右子树的结点的值。若父亲大孩子小,则为大顶堆,若父亲小孩子大,则为小顶堆。 作用:应用于堆排序。

13. M阶B-树和M阶B+树的主要区别 ① B+树所有有效数据全在叶子节点,而B-树所有节点分散在树中,B-树中的关键字不重复。 ② B+树种有几个关键字就有几个子树,B-树中具有n 个关键字的节点含有(n+1)棵子树。 ③ B+树有两个指针,根指针和只想最小节点的指针,叶子节点连接成一个不定长的线性链表 ④ B+树中,每个节点(除根节点外)中的关键字个数 n 的取值范围是⌈m/2⌉<=n<=m,根节点 n 的Lchild Data Rchild 取值 ⑤ 范围是2<=n<=m。B-树中,每个节点(除根节点外的所有最底层非叶子节点)中的关键字取值范围 是 ⑥ ⌈m/2⌉-1<=n<=m-1,根节点n 的取值范围是1<=n<[m-1]。 ⑦ B+树中的所有非叶子节点仅仅起到索引的作用,节点中的每个索引项只包含对应子树的最大关键字 和 指向该子树的指针,不含有该关键字对应记录的存储地址。而在B-树中,每个关键字对应记录的存储 地址。

14.折半查找,以及其适用范围和时间复杂度 又称二分查找,基本思路: 在当前的查找区间[low…high]中,首先确定mid=(low+high)/2,然后拿关键字与mid比较,若相等则查 找成功,返回该位置,否则确定新的查找区间, mid>K,[low…mid-1] mid<K,[mid+1…high] 直至查找自区间长度小于1时查找结束。

适用范围:顺序结构存储并按照关键字大小有序排列。 时间复杂度:O(log2N)

15. 如何实现循环队列?有何好处? 如何实现:把数组弄成一个环,让rear和front指针沿着环走,这样就可以产生循环队列。 好处:循环队列是顺序队列的改进,在顺序队列中,在元素进队的时候,rear 要向后移动,元素出队的时候,front也要向后移动,这样经过一系列的出队和入队操作之后,两个指针最后会达到数组的末端,此时 虽然队中已经没有元素了,但是还是不能让元素入队,即出现了“假溢出”的现象。循环队列就能避免出现这个现象。

循环队列的顺序表中,为什么要空一个位置? 这是为了用来区分队空与队满的情况。如果不空一个位置,则判断队空和队满的条件(front==rear)是一样的。【fornt指向队头元素,rear指向队尾元素的下一个元素】

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值