1:简述下指针?
1指针形象的话称为地址,指向该变量的内存单元。通过它可以找到以它为地址的内存单元。
2:数据结构中树的实现方式?
1顺序存储(数组)
2链式存储(孩子链存储结构/孩子兄弟链存储结构)
3:堆和栈的区别?
申请内存方式:
(1)栈是通过系统自动分配和释放,存储函数的参数和局部变量
(2)堆是通过程序员手动申请并且释放,在C中通过malloc和free函数,C++通过new和delete函数
空间大小:
(1)栈获取空间比较小,当申请内存大于剩余空间时,会溢出
(2)堆的空间和和虚拟内存有关,获取的空间比较大
执行效率:
(1)栈由系统自动分配,比较快,空间连续,不会产生碎片
(2)堆程序员分配比较慢,采用的是链表的存储方式,会产生碎片
4:顺序表和链表的区别
顺序表 链表
连续的存储空间 不连续的存储空间
支持随机访问 不支持随机访问
插入和删除比较方便
5:广度优先和深度优先区别?
深度优先的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到。 若此时尚有其他顶点未被访问到,
则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
特点:选定一个出发点后进行遍历,能前进则前进,若不能前进,回退一步再前进,或再回退一步后继续前进。依此重复,直到所有与选定点相通的所有顶点都被遍历。
广度优先遍历:类似与二叉树的层序遍历算法,它的基本思想是:首先访问起始顶点v,接着由v出发,依次访问v的各个未访
问的顶点w1 w2 w3....wn,然后再依次访问w1 w2 w3....wn的所有未被访问的邻接顶点;再从这些访问过的顶点出发,
再访问它们所有未被访问过的邻接顶点......依次类推, 直到图中的所有点都被访问为止
6:面向对象和面向过程的区别?
我们可以举个例子来说明一下,假如我们现在要下五子棋,分别通过面向对象和面向过程的思想来加以区分?
(1):1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。
把上面每个步骤用分别的函数来实现,问题就解决了。而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为:
(2);1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。
可以明显地看出,面向对象是以功能来划分问题,而不是步骤,面向过程是以步骤来划分问题
7:结构体和联合有什么区别?
(1). 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。
(2). 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的。
8:类和对象的区别?
类和对象之间的关系是抽象和具体的关系,类是对多个对象进行综合抽象的结果,对象是类的实例(eg:猫和狗以及动物之间的关系 猫和狗可以共同抽象为动物,动物是一个抽象概念,而猫和狗是动物的一个实例)
9:int所占的字节数是多少?
int 所占的字节数由编译器和系统决定,我们用的VC int是占四个字节
10:头结点有什么作用?
头结点是指向初始地址的一个节点,它本身数据段没有内容,通过它可以标识这个链表。
11:哈夫曼树的特点?
哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近
12:数组名与指针的区别
数组名不能够自增自减(a+1是正确的,数组名可理解为常量),指针能够自动加减并且按照其数据类型进行缩放。
sizeof(数组名)返回数组空间按字节计算,对指针使用则是返回固定指针字节值。当数组名作为参数传递给函数时,退化为指针
11:最短路径算法;迪杰斯特拉 和弗洛伊德
最小生成树:克鲁斯卡尔和普里姆
12;解决哈希冲突的问题
(1):线性探测法 链地址法 平方探测法
13:简述一下哈希表
它通过把关键值映射到表中一个位置来访问记录,加快查找速度,叫散列函数
14:平衡二叉树(二叉排序树):有完全二叉树
其查找效率为O(Log2n),近似于折半查找。如果二叉排序树完全不平衡,则其深度可达到n,查找效率为O(n),
退化为顺序查找。一般的,二叉排序树的查找性能在O(Log2n)到O(n)之间。因此,为了获得较好的查找性能
,就要构造一棵平衡的二叉排序树
15:double *p[6] p是指针数组,其元素是指向double型变量的指针
16:文件指针是用来存放文件的相关信息(文件名,文件状态,当前文件位置
17:Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径
Floyd算法是解决任意两点间的最短路径的一种算法
时间复杂度区别:迪杰斯特拉 n的平方 Floyd:n的立方
18:static作用
(1):设置变量的作用域和存储域
引用和指针的区别
(1)引用初始化以后不能被改变,指针可以改变
(2)不存在指向空值的引用,存在指向空值的指针
19:全局变量和局部变量在内存中有什么区别
(1):全局变量存储在静态数据区,局部变量在堆栈
:20:堆栈溢出的原因
(1)没有回收垃圾资源
没有回收垃圾资源
21:简述一下C语言
C语言的特点:能直接访问内存物理地址,进行位操作,代码质量高,执行效率高,移植性好。语言简洁,紧凑,数据结构丰富
运算符丰富,具有结构化控制语句。
22:简述一下回调函数
1:就是一个通过函数指针调用的函数,如果你把函数的指针(地址)作为参数传递给另外一个函数,当这个指针被用来调用其
所指向的函数时。就是回调函数
23:简述一下复杂度:
包括时间复杂度和空间复杂度 用来描述一个算法的好坏
24:完全二叉树的特点
(1):只允许最后一层有空缺结点,且空缺结点在右边
(2):右子树深度为k,左子树比为k或者k+1;
度为1的结点个数要么为1或者为0
24:简述一下线索二叉树
线索二叉树是为了充分利用空指针域
ltag为0指向结点的左孩子 为1是指向结点的前驱
rtag为0指向结点的右孩子,为1是指向结点的后继
25:AOV和AOE的区别?
AOV网(Activity On Vertex)
在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称为AOV网
从源点到终点具有最大长度的路径叫关键路径,在关键路径上的活动叫关键活动
AOE 用顶点表示事件,用弧表示活动
AOV 顶点表示活动 边表示优先关系 拓扑排序
要体现在AOV网是顶点表示活动的网,它只描述了活动之间的约束关系,而AOE网是用有向边表示活动,边上的权值表示活动持续的时间。
AOE网是建立在AOV网基础之上(活动之间约束关系没有矛盾),再来分析完成整个工程至少需要多少时间,或者为缩短完成工程所需时间,
应当加快那些活动等问题。
26:简述一下散列表?
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表
27:Java和C++的区别?
(1)Java是解释型语言,所谓的解释型语言,就是源码会先经过一次编译,成为中间码,中间码再被解释器解释成机器码。对于Java而言,中间码就是字节码(.class),而解释器在JVM中内置了。
(2). C++是编译型语言,所谓编译型语言,就是源码一次编译,直接在编译的过程中链接了,形成了机器码。
(3). C++比Java执行速度快,但是Java可以利用JVM跨平台。
(4). Java是纯面向对象的语言,所有代码(包括函数、变量)都必须在类中定义。而C++中还有面向过程的东西,比如是全局变量和全局函数。
(5). C++中有指针,Java中没有,但是有引用。
(6) C++支持多继承,Java中类都是单继承的(用接口实现)
28:指针函数和函数指针的区别?
指针函数本质是一个函数,其返回值为指针。
函数指针本质是一个指针,其指向一个函数的指针变量。
写法不同
指针函数:int* fun(int x,int y);
函数指针:int (*fun)(int x,int y);
指针数组:即用于存储指针的数组,也就是数组元素都是指针,本质上是数组
数组指针:本质上是指针
29:散列函数产生冲突的解决方法?
(1).散列函数是否均匀;
(2). 处理冲突的方法;
(3) 散列表的装填因子。
散列表的装填因子定义为:α= 填入表中的元素个数 / 散列表的长度
α越小,填入表中的元素较少,产生冲突的可能性就越小
除留余数法
取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址.即H(Key)=Key MOD p,p<=m.p的选择很重要,一般取素数或m
30:贪心算法的思想?
贪心算法是一种对某些求解最优问题的更为简单的方法。贪心算法每次都考虑一个局部最优解,总是考虑当前状态下的最优的选择。不从整体最优上加以考虑,只做出在某种意义上的局部最优解。选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
迪杰斯特拉:贪心算法 求单源最短路径
哈弗曼编码也是贪心算法
31:迪杰斯特拉和弗洛伊德的区别?
迪杰斯特拉最最朴素的思想就是按长度递增的次序产生最短路径。即每次对所有可见点的路径长度进行排序后,选择一条最短的路径,
这条路径就是对应顶点到源点的最短路径。
图G中不存在负权值的边 A B C(2,-2,1)
弗洛伊德:可以有负权值 但不存在负权值的回路
迪杰斯特拉属于贪心算法;
弗洛伊德属于动态规划
另外需要注意的是:Floyd-Warshall算法不能解决带有“负权回路”(或者叫“负权环”)的图,因为带有“负权回路”的图没有最短路。
例如下面这个图就不存在1号顶点到3号顶点的最短路径。因为1->2->3->1->2->3->…->1->2->3这样路径中,每绕一次1->-2>3这样的环,
最短路就会减少1,永远找不到最短路。
其实如果一个图中带有“负权回路”那么这个图则没有最短路。
32:动态规划算法的思想
1.动态规划是通过组合子问题的解来解决原问题
2.动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题
3.动态规划算法对每个子子问题只求解一次
4.动态规划通常用来求解最优化问题
33:简述单链表的优点和缺点。:
答:单链表操作灵活,增加、删除元素时只需修改指针,从堆中分配空间,自由度大但难管理,只能顺序存取,不能随机存取。
34:结构化算法与非结构化算法的区别?
结构化算法:是由一些基本结构顺序组成的.在基本结构之间不存在向前或向后的跳转,流程的转移只存在于一个基本的结构范围内.
一个非结构化的算法可以用一个等价的结构化算法代替,其功能不变.
跟结构化算法比较起来,非结构化算法有以下缺点.
流程不受限制的随意转来转去,使流程图豪无规律.使人在阅读的时候难以理解算法的逻辑.难以阅读,也难以修改.从而使算法的可靠性和可维护性难以保证.
35:算法时间复杂度与问题规模关系吗?
算法时间复杂度与问题规模和输入实例中的元素取值等相关,但在最坏情况下,时间复杂度只与问题的求解规模相关。
36:常用的存储表示方式有哪几种?
1:顺序存储方式 2:链式存储方式 3:.索引存储方式;4.散列存储方式
37:说明线性表、栈、队列的异同?
都是线性结构,都是逻辑结构概念,都可以用顺序存储或链式存储
栈和队列是受限的线性表
38:确定循环队列是空还是满的方式有哪些?
1.计数器;2.设布尔变量;3.空出一个元素:
2:数据项不可分割的最小单位 数据元素是数据的基本单位
数据元素之间的关系:线性 树 图 集合
39:逻辑结构和存储结构的区别:
逻辑结构:指各数据元素之间的逻辑关系。
存储结构:就是数据的逻辑结构用计算机语言的实现。
一种逻辑结构在计算机里可以用不同的存储结构实现
40:C语言中存储说明符?
auto:用于修饰局部变量
static:只能在本源程序文件使用
extern:在外部程序文件使用
41:线性结构和非线性结构的区别?
线性结构表示数据元素之间一对一的关系,非线性结构表示数据元素之间一对多或多对一的关系。 线性结构:线性表 非线性结构:图 树
42:int *p1,float *p2所占的内存字节数?
这三种类型的变量所占内存大小是一样的。因为指针变量只需要存储一段内存单元的首
地址。
43:简述一下邻接矩阵和邻接表?
邻接矩阵的优点是可以快速判断两个顶点之间是否存在边,可以快速添加边或者删除边。而其缺点是如果顶点之间的边比较少,会比较浪费空间
邻接表的优点是节省空间,只存储实际存在的边。其缺点是关注顶点的度时,就可能需要遍历一个链表。
44:简述一下KMP算法?
KMP算法:在一个字符串中查找是否包含目标的匹配字符串。其主要思想是每趟比较过程让子串先后滑动一个合适的位置。
当发生不匹配的情况时,不是右移一位,而是移动
(当前匹配的长度– 当前匹配子串的部分匹配值)位。
要求在某个字符串中找出与该子串相同的所有子串,这就是模式匹配。
子串:目标串
主串:模式串
45:堆的定义以及所满足的条件?
(1)是完全二叉树
大根堆:父结点的值大于等于其子结点的值;
小根堆:父结点的值小于等于其子节点的值
46:栈的应用?
栈的应用场景包括括号问题的求解,表达式的转换和求值,函数调用和递归实现,深度优先搜索遍历等;
常见的队列的应用场景包括计算机系统中各种资源的管理,消息缓冲器的管理和广度优先搜索遍历等于其子结点的值;
47:栈和队列的相同之处?
都是线性结构
插入操作都是在表尾进行
插入和删除的时间复杂度都是O(1),在空间复杂度上也相同
都可以通过顺序结构和链表实现
不同之处在哪里?
①删除数据元素的位置不同,栈在表尾进行,队列在表头进行
应用场景不同 栈先进后出 队列先进先出
48:树的双亲存储结构和链式存储结构
(1)孩子链式存储结构
(2)儿子兄弟链式存储结构
邻接矩阵是图的顺序存储结构
邻接表是图的一种链式存储结构
49:图的基本概念
第一个顶点和最后一个顶点相同的路径称为回路或环
在路径序列中,顶点不重复出现的路径称为简单路径。
除第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路称为简单回路
图的深度优先搜索(DFS)类似于二叉树的先序遍历。时间复杂度O(|V|+|E|)O(|V|+|E|)
图的广度优先搜索(BFS)类似于树的层次遍历,对于邻接表复杂度O(|V|+|E|)O(|V|+|E|)
每个顶点均需搜索一次(或入队一次),每条边至少访问一次。
连通图:设图G是无向图,当且仅当G的每一对顶点之间都有一条路径,则称G是连通图。
强连通图:图G是一个有向图,当且仅当每一对不同的顶点u,v,从u到v和v到u都有一条有向路径。
数据元素:数据的基本单位
数据项:构成数据元素的不可分割的最小单位。
存储结构也是物理结构
程序=算法+数据结构
好的算法:正确、可读、健壮、效率与储存量
时间复杂度:语句可重复执行次数
空间复杂度:算法消耗的存储空间
数据结构 :指相互之间存在一定关系的数据元素的集合
线性结构 数据元素之间一对一的关系。包括:线性表、栈与队列、串。其特点是
除第一个外,每个元素有且只有一个前驱
除最后一个外,每个元素有且只有一个后继
顺序存储结构 :用元素在存储器中的相对位置来表示数据元素间的逻辑关系
链式存储结构 :用一组任意的存储单元存储数据元素,数据元素之间的逻辑关系是用指针来表示的。
索引存储结构 :采用附加的索引表的方式来存储节点信息的一种存储方式。索引表由若干索引项组成。
索引存储方式中索引项的一般形式为(关键字、地址)。其中,关键字是能够唯一标识一个节点的数据项。
散列存储方式 :根据节点的关键字直接计算出该节点的存储地址
查找算法有哪些?
顺序查找
折半查找
分块查找(块间有序 块内无序)
生成树?
一个连通图的生成树是指一个极小连通子图,一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。
最小生成树中?
所有边的代价和最小的生成树
无向图的定义?
由边和顶点构成的图叫无向图
有向图:若图G中的每条边都是有方向的
:
B+树与B-树相同点在于:
1. 对于一颗M阶B+和B-树来说,根节点的分支数范围为[2,m],非根结点的分支数范围为[m/2(向上取整),m]
2. 所有叶子结点都在同一层
3. 插入操作都是在叶子结点完成(破坏结构后再向上调整)
不同点:B-
4.每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)
5.非叶子结点的关键字个数=指向儿子的指针个数-1;
B+:
非叶子结点的子树指针与关键字个数相同;
所有关键字都在叶子结点出现;
B+的搜索与B-树也基本相同,区别是B+树只有达到叶子结点才命中(B-树可以在
非叶子结点命中)
2、简述快速排序过程
1)选择一个基准元素,通常选择第一个元素或者最后一个元素,
2)通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的元素值比基准值大。
3)此时基准元素在其排好序后的正确位置
4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
B树和B+树的区别,以一个m阶树为例。
关键字的数量不同;B+树中分支结点有m个关键字,其叶子结点也有m个,其关键字只是起到了一个索引的作用,但是B树虽然也有m个子结点,但是其只拥有m-1个关键字。
存储的位置不同;B+树中的数据都存储在叶子结点上,也就是其所有叶子结点的数据组合起来就是完整的数据,但是B树的数据存储在每一个结点中,并不仅仅存储在叶子结点上
B树在找到具体的数值以后,则结束,而B+树则需要通过索引找到叶子结点中的数据才结束,也就是说B+树的搜索过程中走了一条从根结点到叶子结点的路径。
顺序存储:借助数据元素在存储空间中的相对位置来表示元素之间的逻辑关系
链式存储:借助表示数据元素存储地址的指针表示元素之间的逻辑关系
三叉链表:它的结点比二叉链表多一个指针域parent,用于执行结点的双亲,便于查找双亲结点
二叉查找树:二叉查找树又称二叉排序树
a、若它的左子树不空,则左子树上所有结点的值均小于根结点的值
b、若它的右子树不空,则右子树上所有结点的值均大于根结点的值
c、它的左、右子树也分别是二叉查找树
堆:堆是具有以下特性的完全二叉树
若堆中所有非叶子结点均不大于其左右孩子结点,则称为小顶堆(小根堆),若堆中所有非叶子结点均不小于其左右孩子结点,则称为大顶堆(大根堆)
栈通常采用的两种存储结构是(线性存储结构和链表存储结构)
链表的特点是:不必事先估计存储空间(动态内存分配), 插入删除不需要移动元素, 所需空间与线性表长度成正比
用链表表示线性表的优点是(便于插入和删除操作)
50: 在单链表中,增加头结点的目的是(方便运算的实现):
循环链表的主要优点是(从表中任一结点出发都能访问到整个链表)
单链表:除第一个和最后一个元素外,其余每个元素都有一个且只有一个前驱和后继
单向链表相比,双向链表的优点之一是(更容易访问相邻结点)
数据结构包括数据的逻辑结构、数据的存储结构以及对数据的操作运算
顺序存储方法是把逻辑上相邻的结点存储在物理位置相邻的存储单元中。
51:引用和指针的相同点
1、指针和引用都可以优化传参效率
2、都是地址的概念;指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。
52:引用和指针的不相同点
1、指针占内存空间,引用不占内存空间
2、指针可以为空,但是引用不能为空
3、指针可以不初始化,但是引用必须初始化
4、指针可以有多级,但是引用只能是一级(int **p合法但是int &&a是不合法的)
5、指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了,从一而终。
6、指针是一种变量,而引用只是引用。