1.一个包含n个结点的四叉树,每一个节点都有4个指向孩子节点的指针,这4n个指针有(3*n+1)个空指针.
4*n-(n-1) = 3*n+1
最简单的理解就是,n个节点一定就有4n个指针。
除了root节点,所有的节点都用了一个指针,就是用了n-1个
所以答案就是 4n -n +1 = 3n +1
2.求数的二进制表示中1的个数的“平行算法”
int BitCount4(unsigned int n)
{
n = (n &0x55555555) + ((n >>1) &0x55555555) ;
n = (n &0x33333333) + ((n >>2) &0x33333333) ;
n = (n &0x0f0f0f0f) + ((n >>4) &0x0f0f0f0f) ;
n = (n &0x00ff00ff) + ((n >>8) &0x00ff00ff) ;
n = (n &0x0000ffff) + ((n >>16) &0x0000ffff) ;
return n ;
}
速度不一定最快,但是想法绝对巧妙。 说一下其中奥妙,其实很简单,先将n写成二进制形式,然后相邻位相加,重复这个过程,直到只剩下一位。
以217(11011001)为例,有图有真相,下面的图足以说明一切了。217的二进制表示中有5个1
1 1 0 1 1 0 0 1
2 + 1 1 + 1
3 + 2
5
除此之外还有静态表-8bit 4bit 动态建表 普通法 快速法
快速法:
这种方法速度比较快,其运算次数与输入n的大小无关,只与n中1的个数有关。如果n的二进制表示中有k个1,那么这个方法只需要循环k次即可。其原理是不断清除n的二进制表示中最右边的1,同时累加计数器,直至n为0,代码如下
int BitCount2(unsigned int n)
{
unsigned int c =0 ;
for (c =0; n; ++c)
{
n &= (n -1) ;
}
return c ;
}
为什么n &= (n – 1)能清除最右边的1呢?因为从二进制的角度讲,n相当于在n - 1的最低位加上1。举个例子,8(1000)= 7(0111)+ 1(0001),所以8 & 7 = (1000)&(0111)= 0(0000),清除了8最右边的1(其实就是最高位的1,因为8的二进制中只有一个1)。再比如7(0111)= 6(0110)+ 1(0001),所以7 & 6 = (0111)&(0110)= 6(0110),清除了7的二进制表示中最右边的1(也就是最低位的1)。
3.10.(2分)数据库的事务隔离级别一般分为4个级别,其中可能发生“不可重复读”的事务级别有() BC
A、SERIALIZABLE
B、READ COMMITTED
C、READ UNCOMMITTED
D、REPEATABLE READ
解析:四个级别
串行化(SERIALIZABLE):所有事务都一个接一个地串行执行,这样可以避免幻读(phantom reads)。对于基于锁来实现并发控制的数据库来说,串行化要求在执行范围查询(如选取年龄在10到30之间的用户)的时候,需要获取范围锁(range lock)。如果不是基于锁实现并发控制的数据库,则检查到有违反串行操作的事务时,需要滚回该事务。
可重复读(REPEATABLE READ):所有被Select获取的数据都不能被修改,这样就可以避免一个事务前后读取数据不一致的情况。但是却没有办法控制幻读,因为这个时候其他事务不能更改所选的数据,但是可以增加数据,因为前一个事务没有范围锁。
读已提交(READ COMMITED):被读取的数据可以被其他事务修改。这样就可能导致不可重复读。也就是说,事务的读取数据的时候获取读锁,但是读完之后立即释放(不需要等到事务结束),而写锁则是事务提交之后才释放。释放读锁之后,就可能被其他事物修改数据。该等级也是SQL Server默认的隔离等级。
读未提交(READ UNCOMMITED):这是最低的隔离等级,允许其他事务看到没有提交的数据。这种等级会导致脏读(Dirty Read)。
4.类成员的初始化顺序是和成员在类中的声明顺序一致的!所以_data是在_size之前就初始化好了,调用的默认构造函数,所以里面没有元素。
编译器:gcc4.7
5.写程序判断当前CPU是大端CPU还是小端CPU,并做简要说明。
最简单的方式就是利用union的特性,由于联合的大小和最大成员的大小一样,里面的成员是共享存储空间的。
int checkCPU( ){
union w {
int a;
char b;
} c;
c.a = 1;
return(c.b ==1);
}
解析:
大端格式:在这种格式中,字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中,
小端格式:与大端存储格式相反,在小端存储格式中,低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节。
现在主流的CPU,intel系列的是采用的little endian的格式存放数据,而motorola系列的CPU采用的是big endian,ARM则同时支持 big和little,网络编程中,TCP/IP统一采用大端方式传送数据,所以有时我们也会把大端方式称之为网络字节序。
C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而 Java编写的程序则唯一采用big endian方式来存储数据。
6.
利用位运算实现两个整数的加法运算,请代码实现,并做简要说明。
int Add(int a, int b)
{
int sum = a ^ b;
int carry = a & b;
while (carry != 0) {
a = sum;
b = carry << 1;
sum = a ^ b;
carry = a & b;
}
return sum;
}
首先用sum记录a和b二进制中不同的位置为1(异或运算,不同为1),carry记录相同位为1(与运算,相同为1得1),这时候a+b就可以化为sum+(carry<<1),不断将carry右移,当carry为0的时候,sum的值就是最终结果。
7.volatile的作用是: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.