一、C/C++
- 所谓私有成员是指只有类中所提供的成员函数才能直接使用它们,任何类以外的函数对它们的访问都是非法的。(x) 【友元函数】
C语言函数入栈的顺序:参数由右向左
,参数 i 先入栈,输出 0,在后执行 i++,此时 i 为 1,接着参数执行 ++i,i 为 2.
数组传递了首地址,b[0][0] 指向数组 a[0][0] ,但是执行 ++b后,b[0][0] 指向 a[1][0] ,因此 b[1][1] 就是 a[2][1],b[1][1]=9即a[2][1]=9。
引用不是对象,因此不能定义一个指向引用的指针,但是可以定义指针的引用。
友元函数一般定义在类的外部,但需要在类体内进行声明,且需要在前面加上 friend 关键字。友元函数不是成员函数,但是它可以访问类的私有成员。
- static
求下列输出结果为?
static int fun(int j)
{
static int i = j;
return ++i;
}
int main()
{
int i = 0;
int j = 128;
for(; j > 0; j--)
{
i = fun(j);
}
cout << i << endl;
return 0;
}
i = 256;在fun函数内部 i 只会被第一次的 j 初始化,在之后都将不会被初始化。
段错误。不能修改常量。
void test2()
{
int *a[10]; // a指向里面存放了10个int*类型的指针
int (*b)[10]; // b仅仅是个指针,是一个指向有10个元素的数组
cout << sizeof(a) << endl; // 40
cout << sizeof(b) << endl; // 4
}
dynamic_cast是运行时检查,虽然 pb1是A1类型的,但是指向的实体却是子类,所以子类转父类是可以的。但是 static_cast 是编译期检查,而多态是在运行起才动态转换的,于是发现pb1是A1类型,就会报错。
p为指向一个有3个元素的指针,存储的是10,20,30。
二、操作系统
- 特权指令:主要用于系统资源的分配和管理
三、网络
磁盘空间利用率:记录块大小 * 块因子 / 物理块大小
本题:80 * 4 / 512
- 一个程序,在 A 服务器上运行正常,但是在 B 服务器运行出错,两个服务器的的系统一致,怎么排查这个错误?
如果系统一致,软硬件一致,那可以定位问题在:
- 程序本身的鲁棒性(健壮性)不强,当某些条件稍微变化,程序直接崩溃的,比如网络不稳定,使用的某些资源不存在导致的崩溃。
- 程序本身依赖的第三方资源可能版本各方面不完全一致,在使用的时候,结果可能不符合预期,程序直接崩溃。
- 服务器的负载不同,也可能会有这个问题,一个服务器的压力大,一个小。服务器会在压力特别大的时候终止部分进程
- 如果是数据库相关的服务,在进一步考虑一下数据库的问题。
四、数据结构
1. 哈希
【哈希解决冲突的四种方法】
- 开放地址法:包括 线性探测法,平方探测法
- 线性探测法:
fi(key) = (f(key)+di) MOD m (di=1,2,3,……,m-1)
- 平方(二次)探测法:
fi(key) = (f(key)+di) MOD m (di=1,-1, 4, -4, 9, -9, k^2, -k^2) k <= 2/m
- 再哈希法(再散列法):需要多个不同的 hash 函数
-
链地址法:每个哈希节点都有一个 next 指针,多个哈希节点可以用 next 指针构成一个单向链表,被分配到同一索引上的多个节点可以用这个单向链表连接起来。
-
建立公共溢出区:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。
该题解法:
49%11=5被占用了
(5+1^2)%11=6还是被占用了
(5-1^2)%11=4被占用了
(5+2^2)%11=9未被占用,所以在9的位置放入49
2. 稀疏矩阵
稀疏矩阵:矩阵中大多元素都为 0 元素,用一个三元组存放矩阵中的元素,形式为(i,j,e)
i:行号;j:列号;e:元素的值
所以该题的稀疏矩阵为:
0 3 0 0 0 1
0 0 0 0 0 0
5 -1 0 0 0 0
0 0 0 0 0 0
-3 0 0 5 0 0
转置矩阵为:交换(x,y)
0 0 5 0 -3
3 0 -1 0 0
0 0 0 0 0
0 0 0 0 5
0 0 0 0 0
1 0 0 0 0
矩阵压缩
- 对称矩阵:
K = i * (i-1) / 2 + j - 1 (i <= j); K = j * (j -1) / 2 (j > i)
- 下三角矩阵:矩阵(除主对角线)的上三角部分的值均为一个常数 C 或者 0。可以得出,当 i <= j 时,与对称矩阵类似,但是上三角我们可以只用一个元素来存储,K = n*(n+1)/2
- 上三角矩阵:
K = (i-1)(2n-i+2) / 2 + j - 1 (i <= j); K = n* (n+1) / 2 (j > i)
若在内存中,则数据可以随机存取,但内存数据被读取或写入时,所需要的时间与这段信息所在的为止无关,但是在读取和写入磁盘时,其所需要的时间与位置就会有关系。因为很多语言中,数组都是按行存放的,也就是每行的数据都是连续的,而每列的数据是不连续的,这样可能需求的内存地址不在当前页中则需要进行页置换,所以速度更慢。
3. 树
- 哈夫曼树
最优二叉树
:给定 N 个权值作为 N 个叶子节点,构造一颗二叉树,若该树的带权路径长度达到最小,称这样的二叉树为哈夫曼树。哈夫曼树是带权路径长度最短的树,权值较大的节点离根节点较近。
- 线索二叉树
线索二叉树的线索树就是空指针域的数目。一个有 n 个节点的线索二叉树,每个节点都有指向左右孩子的两个指针域,则共有2n个指针域,而n个节点有 n-1 条分支,所以共有 2n-(n-1) 个空指针域。
- 后序线索树
该题为 D。
- 堆排序平均复杂度为 NlogN,确定一个数的位置为 logN,N个数为 NlogN。
- 从非叶子节点开始调整,最优的情况,就是不需要调正,但是需要遍历 N/2 个节点,为 O(N)。
4. 顺序表
- 找块:(1+2+3+4+5)/ 5 = 3
- 找元素:(1+2+3+4+5+6)/ 6 = 3.5
- 3 + 3.5 = 6. 5
5. 排序
五、Linux
spinlock
:自旋锁,任何时刻只有一个线程能够获取锁,其他线程忙等待直到锁
。spinlock 在多处理器多线程环境的场景下有很广泛的使用。spinlock 不会导致线程的切换状态,mutex 获取不到锁会 sleep。
后台运行可以有两种方式:1. 命令前加 nohup # nohup *.sh;2. 命令后加 &(默认状态) # *.sh
用户级线程
:不需要内核支持而在用户程序中实现的线程,但线程的调度需要用户程序完成。内核级线程
:由内核完成线程的调度。- 用户线程不需要额外的内核开支,但是当一个线程因 I/O 而处于等待状态时,整个进程就会被调度程序切换为等待状态并且其他线程也得不到运行的机会;二内核线程没有这个限制,有利于发挥处理器的并发优势,但却占用了更多的系统开支。
setuid 位是让普通用户可以以 root 用户的角色运行只有 root 账户才能运行的程序或命令。因此当程序设置了 setid 权限位时,普通用户会临时变成 root 权限,但实际的用户(执行程序的用户)仍然是原来的 mike。
子进程独有:
- 进程ID
- 自己的文件描述符和目录流的拷贝
- 阻塞集初始化为空集
- 父子进程有独立的地址空间和pid 参数。
位示图法:利用一串二进制位的值来反映磁盘空间的分配使用情况。
空闲块法:文件系统建立了一张全部空闲物理块的空闲块表。
空闲块链表法:系统将所有的空闲物理块连成一个空闲块链表,用一个指针指向第一个空闲块,每个空闲块含有指向下一个空闲块的指针,最后一块的指针指向 NULL,表示达到连尾。
UNIX/Linux 系统等大型文件系统采用的是成组链接法。把所有空闲块按固定数量分组,组与组之间形成链接关系,这就是成组链接法。