2017阿里实习生笔试题(二)
下面哪一个不是动态链接库的优点?
A.共享
B.装载速度快
C.开发模式好
D.减少页面交换
静态链接与动态链接:
1 静态链接库的优点
(1) 代码装载速度快,执行速度略比动态链接库快;
(2) 只需保证在开发者的计算机中有正确的.LIB文件,在以二进制形式发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题,可避免DLL地狱等问题。
2 动态链接库的优点
(1) 更加节省内存并减少页面交换(静态库把所有的文件都装入了,而动态库只是装入了部分需要的);
(2) DLL文件与EXE文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性;
(3) 不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数;
(4)适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。
3 不足之处
(1) 使用静态链接生成的可执行文件体积较大,包含相同的公共代码,造成浪费;
(2) 使用动态链接库的应用程序不是自完备的,它依赖的DLL模块也要存在,如果使用载入时动态链接,程序启动时发现DLL不存在,系统将终止程序并给出错误信 息。而使用运行时动态链接,系统不会终止,但由于DLL中的导出函数不可用,程序会加载失败;速度比静态链接慢。当某个模块更新后,如果新模块与旧的模块 不兼容,那么那些需要该模块才能运行的软件,统统撕掉。这在早期Windows中很常见。
由权值分别为1、12、13、4、8的叶子节点生成一颗哈夫曼树,它的带权路径长度为()
哈弗曼树:哈夫曼树是一种带权路径长度最短的二叉树,也称为最优二叉树。
就拿上图例子来说:
A,B,C,D对应的哈夫曼编码分别为:111,10,110,0
假设从上至下地址递增,则 PowerPC(大): Intel X86(小): 04 01 低 03 02 | 02 03 | 01 04 高
a+3指向最大的地址,所以分别为1 4
经历SYN_RECV状态
经历SYN_SEND状态
经历ESTABLISHED状态
经历TIME_WAIT状态
服务器在收到syn包时将加入半连接队列
服务器收到客户端的ack包后将从半连接队列删除
问题描述:
#pragma pack(2) class BU { int number; union UBffer { char buffer[13]; int number; }ubuf; void foo(){} typedef char*(*f)(void*); enum{hdd,ssd,blueray}disk; }bu;
第一行的使得对齐的补齐字节为2。
因此union的大小为13+1=14.
void foo(){} 不占 ——函数不占用sizeof的内存。
typedef char*(*f)(void*); 不占——声明不占用内存
enum{hdd,ssd,blueray}disk; 4个字节—— -- 实质上就是整型,所以 size 是 4
在动态分区分配方案中,系统回收主存,合并空闲空间时需修改空闲区表,以下哪种情况空闲区会减1?
A.只要回收主存,空闲区数就会减一
B.空闲区数和主存回收无关
C.无上邻空闲区,也无下邻空闲区
D.有上邻空闲区,但无下邻空闲区
E.有下邻空闲区,但无上邻空闲区
F.有上邻空闲区,也有下邻空闲区
int* pint = 0; pint += 6; cout << pint << endl;
以上程序的运行结果是: 24
首先如果直接cout一个指针,打印的是其所村春的变量的地址。
这个指针+6,一个指针的大小是4,加4*6就是24.
下面哪种协议在数据链路层?
ARP
ICMP
FTP
UDP
HTTP
VPN
ICMP是网络层,UDP是传输层,FTP和HTTP是应用层
目前VPN隧道协议主要有4种:点到点隧道协议PPTP、第二层隧道协议L2TP、网络层隧道协议IPSec以及SOCKS v5协议。其中,PPTP和L2TP工作在数据链路层,IPSec工作在网络层,SOCK v5工作在会话层。
TCP/IP模型中,ARP协议属于网络层,在OSI参考模型中,ARP属于数据链路层
以下哪种方式,在读取磁盘上多个顺序数据块时的效率最高?
中断控制方式
DMA方式
通道方式
程序直接访问方式
循环检查I/O方式
以上访问方式都一样
C/C++工程师能力评估
以下prim函数的功能是分解质因数。括号内的内容应该为?
void prim(int m, int n) { if (m >= n) { while ( ) n++; ( ); prim(m, n); cout << n << endl; } }
m/=n m%=n
分解质因数:从n=2开始,找到第一个m的质因子,因此需要m&n==0,然后继续找剩下的质因子,此时m=m/n。也可以用循环法做,此处不再赘述。
补充一下判断是否为质数的代码:
int isPrime(int n) { int flag = 1; for(int i = 2; i*i <= n; i++) if(n%i == 0) flag = 0; return flag; }
补充一下最大公约数的代码:(辗转相除法)
int gcd(int x,int y) //用辗转相除法,求两数的最大公约数 { int r; while(y>0) { r=x%y; x=y; y=r; } return x; }
求两数的最大公约数,可采用欧几里得方法:只要两数不相等,就反复用大数减小数,直到相等为止,此相等的数就是两数的最大公约数。
int gcd(int x,int y) { while(x!=y) { if(x>y) x=x-y; else y=y-x; } return x; }
补充一下最小公倍数的代码:先求出最大公约数,用x*y/gcd(x,y)就可以得到最小公倍数。
enum string{ x1, x2, x3=10, x4, x5, } x;
函数外部问x等于什么?0
- 数组在当做参数传给函数的时候,会被退化为普通指针,因此,sizeof还是4字节。
- 指针在做加减的时候,是根据其所指的类型进行加减的,因此加减sizeof(type)。
- 静态局部变量要比全局变量先销毁。
- 重载和重写的一些要求:
char
(* ss)[N]表示是一个指向一个数组(字符串数组),这个数组存的类型是——char[N],即又是一个一位数组。
- 类的大小注意点:
1 先找有没有virtual 有的话就要建立虚函数表,+4
2 static的成员变量属于类域,不算入对象中,成员函数也不占空间 +0
3 神马成员都没有的类,或者只有成员函数 +1
4 对齐法则,对大家都没有问题,看看有没有被#pragma pack(n)设置大小
int main() { MyClass obj1(1), obj2(2); MyClass obj3 = obj1; return 0; }
关于拷贝构造和赋值的问题:以上例子中obj3调用的是拷贝构造函数,因为obj3还未存在,需要调用拷贝构造函数。
假如obj3已经存在,才会调用赋值函数。
数组全排列:
void perm(int list[], int k, int m) { if (k==m) { copy(list,list+m,ostream_iterator<int>(cout," ")); cout<<endl; return; } for (int i=k; i<=m; i++) { swap(&list[k],&list[i]); perm(list,k+1,m); swap(&list[k],&list[i]); } }
腾讯2016研发工程师在线模拟笔试题
1、 32位系统中,定义**a[3][4],则变量占用内存空间为()。
解析:**a[3][4]表示a存储的地址,指向一个大小为3*4的数组,这个数组里存储的是指针。指针大小为4,4*3*4=48。
2、有36辆自动赛车和6条跑道,没有计时器的前提下,最少用几次比赛可以筛选出最快的三辆赛车?
解析:6次得到小组第一,a1 b1 c1 d1 e1 f1,def所在的小组的二三名舍弃。
第七次,a1,b1,c1,d1,e1,f1进行比赛。得到前三,假设为b1,d1,e1。则a1,c1,f1被舍弃。
第八次,在b2,b3,d1,d2,e1种得到第二名和第三名。
3、下列哪些http方法对于服务端和用户端一定是安全的?()
解析:
Get:通过请求URI得到资源。
Post:不仅可以查询也可以添加新的内容,请求放在Body里。
Head:类似于Get,但是不返回body,获得请求uri的响应报头,用于检查对象是否存在。
Trace:用于远程诊断服务器。
Options:列出请求的资源支持的所有方法。
Head、Get、Options和Trace视为安全的方法,因为它们只是从服务器获得资源,而不对服务器做任何修改,但对于用户端未必安全。例如get容易将敏感信息暴露在uri中。
4、一个系统,提供多个http协议的接口,返回的结果Y有json格式和jsonp格式。Json的格式为 {"code":100,"msg":"aaa"},为了保证该协议变更之后更好的应用到多个接口,为了保证修改协议不影响到原先逻辑的代码,以下哪些设 计模式是需要的?协议的变更指的是日后可能返回xml格式,或者是根据需求统一对返回的消息进行过滤。()
解析:装饰者模式:动态添加功能,例如过滤功能,并不修改原来的逻辑。
proxy模式:为类提供代理,使得代理类可以控制对 对象的访问,例如实现延迟实例化,控制访问等。
composite模式:组合模式,将对象组合成树形结构以表示"部分-整体"的层次结构。使得用户对单个对象和组合对象的使用具有一致性。
5、对于定义"int *p",下列哪些说明可能是正确的?()
int (*p)「10」才表示一个指向一位数组的指针。
int * (*p)「10」表示一个指向二位数组的指针。
int arr「10」;
int *p=arr;此时p保存的是第一个元素的地址。
6、十字链表是无向图的一种存储结构()是
解析:
图的存储结构:
邻接矩阵,也成为数组表示法。用一个一维数组存储图中顶点的信息,用一个二维数组存储边的信息。
邻接表:是一种顺序存储和链式存储结合的存储方法。
十字链表:即把每一条边的边结点分别组织到以弧尾顶点为头结点的链表和以弧头顶点为头顶点的链表中。在十字链表表示中,顶点表和边表的结点结构分别如图8.13 的(a)和(b)所示。
7、在一个元素个数为N的数组里,找到升序排在N/5位置的元素的最优算法时间复杂度是 O(n)
解析:算法课上讲过的,线性复杂度的找第K大的元素的算法。
BFPRT算法解决的问题十分经典,即从某n个元素的序列中选出第k大(第k小)的元素,通过巧妙的分 析,BFPRT可以保证在最坏情况下仍为线性时间复杂度。
该算法的思想与快速排序思想相似,当然,为使得算法在最坏情况下,依然能达到o(n)的时间复杂 度,五位算法作者做了精妙的处理。
算法步骤:
1. 将n个元素每5个一组,分成n/5(上界)组。
2. 取出每一组的中位数,任意排序方法,比如插入排序。
3. 递归的调用selection算法查找上一步中所有中位数的中位数,设为x,偶数个中位数的情况下设定为选取中间小的一个。
4. 用x来分割数组,设小于等于x的个数为k,大于x的个数即为n-k。
5. 若i==k,返回x;(i就是中位数)
若i<k,在小于x的元素中递归查找第i小的元素;
若i>k,在大于x的元素中递归查找第i-k小的元素。
终止条件:n=1时,返回的即是i小元素。
8、下面的程序输出可能是什么?一直是“ab”
class Printer{ public: Printer(std::string name) {std::cout << name;} }; class Container{ public: Container() : b("b"), a("a") {} Printer a; Printer b; }; int main(){ Container c; return 0; }
初始化列表的初始化顺序 与在列表中的顺序无关,由变量在类中定义的先后顺序决定.
因此先初始化a,然后再初始化b。
还有一种题目:
class A { private: int n1; int n2; public: A():n2(0),n1(n2+2){} void Print(){ cout << "n1:" << n1 << ", n2: " << n2 <<endl; } }; int main() { A a; a.Print(); return 1; }
这个题目,因为先初始化n1,此时n2还未初始化,所以是未定义值。后来n2才被初始化为0.因此结果是下图:
9、下面程序段包含4个函数,其中具有隐含this指针的是() f4
int f1(); class T { public:static int f2(); private:friend int f3(); protect:int f4(); };
解析:
10、如果在一个排序算法的执行过程中,没有一对元素被比较过两次或以上,则称该排序算法为节俭排序算法,以下算法中是节俭排序算法的有________。插入排序,归并排序
解析:
A。插入排序的思想是对第i+1位置上的数,将其插入前i个有序数组中。插入以后形成新的有序数组,根据排序数组不会在比较的原则,该元素不可能再次比较了。
结点的带权路径长度:结点到树根之间的路径长度与该结点上权的乘积。
哈夫曼编码:(左1右0/左0右1)。得到码表,根据出现的概率乘以码长可以得到平均码长。平均码长/等长编码=压缩率。
哈夫曼编码步骤:(找最小权值的节点拿出来构成一颗二叉树,生成一个中间节点,再重复)
一、对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F= {T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算 法,一般还要求以Ti的权值Wi的升序排列。)
二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
四、重复二和三两步,直到集合F中只有一棵二叉树为止。
12、若以下程序
#include <stdio.h> main() { FILE *fp; int i,a[ 6]={1,2,3,4,5,6},k; fp = fopen ("data.dat", "w+b"); for (i=0;i<6;i+ +) { fseek(fp,0L,0); fwrite(&a[5—i],sizeof(int),1,fp); } rewind(fp); fread(&k,sizeof(int),1,fp); fclose(fp); printf("%d",k); }
解析:
C的关于文件I/O的函数库,首先定义了一个文件流fp。然后以w+b的方式打开data文件。下图是open的mode选项:r读w写a追加 加b表示binary二进制模式然后fseek 用于二进制方式打开的文件,移动文件读写指针位置。最后开头只有1。将文件内部的位置指针重新指向一个流(数据流/文件)的开头。654321,每次都写开头,都覆盖模式。
rewind(fp);也是将读写指针移到开头。最后读入k只有1.
13.对{05,46,13,55,94,17,42}进行基数排序,一趟排序的结果是:()42,13,94,05,55,46,17
解析:
14、下列关于bool,int,float,指针类型的变量a 与“零”的比较语句正确的有?
bool : if(!a)
int : if(a == 0)
float: if(a == 0.0) 错误:
指针: if(a == NULL)