1、进程切换的过程是怎样的?什么是用户态,核心态?什么时候发生进程切换?
2、如何编写一个线程安全的HashMap?
3、java集合中ArrayList,LinkList,Vector的区别?
4、c语言中的malloc和c++中的new有何区别?
5、c语言中的静态库和动态链接库的区别?
6、网络中的大端和小端的区别?
7、Hash算法中解决"冲突"的办法有哪些种?
8、各种排序算法的复杂度,什么情况下出现最差情况?
9、在C++程序中调用被 C编译器编译后的函数,为什么要加 extern “C”?
10、java中传递数组,是传值还是传引用?
11、实现一个非递归的fabonacci数列。
12、一个单链表,提供一个指向某个节点的指针,如何删掉这个节点?(没有提供前驱节点)
13、java中">>>"表示什么?
14、如何不用局部变量和全局变量求字符串的长度?
15、链表的逆序算法。
16、面向row的数据库和面向column的数据库的区别,有何优势?
17、设计一个搜索功能需要哪些模块?什么是倒排索引?
【解答】 仅供参考。版权所有,如有转载请注明出处:blog.csdn.com/whuslei
1、参看《操作系统原理》。
进程切换:进程切换发生在核心态模式,由于进程从用户态陷入核心态时已经将用户进程用到通用寄存器的值,用户态的一些特殊寄存器cs,eip,ss,esp等保存在进程的内核堆栈之中,因此在核心态进行进程切换的主要工作是完成内核堆栈的切换和相关硬件上下文的切换。
用户态:是用户程序执行时机器所处的状态。
核心态:是操作系统内核运行时机器所处的状态。
发生条件:进程结束、时间片用完、被抢占、等待io被阻塞。
2、加读写锁,写优先原则。如果有写操作,则不允许读。若没有写操作,可以同时多个读操作
JDK1.5 中java.util.concurrent.locks.ReadWriteLock 的读写锁
rwlock.readLock().lock();//加读锁,允许同时读,读不会阻塞,但会阻止写操作。
value = map.get(key);
rwlock.readLock().unlock(); 比单独加一把排他锁要好。排他锁之允许一次读写操作,具有排他性。 参看http://www.son1c.cn/show/812.html
3、ArrayList 底层是用数组实现的,查询、更新快,删除慢(不适合频繁删除的情况) 。
LinkedList 底层是用双向链表实现的,查询、更新慢,删除快。
Vector 类似于ArrayList,底层也是用数组实现的,但是它是同步的,也就是一个线程使用它时,另一个线程试图去修改它,则会抛出ConcurrentModificationException异常。效率相对ArrayList来说要差些。参看http://www.cnblogs.com/mgod/archive/2007/08/05/844011.html
Collection
├List /**允许重复的value集合*/
│├LinkedList /**用双向链表实现*/
│├ArrayList /**非同步,用数组实现,自增为原来长度的50%*/
│└Vector /**同步,用数组实现,自增为原来的一倍*/
│ └Stack /**用vector实现栈结构*/
└Set /**不允许重复的value集合*/
├HashSet
├LinkedHashSet
└TreeSet
Map /**不允许重复的key-value集合*/
├Hashtable /**同步,key-value,不允许key为null*/
├HashMap /**非同步,key-value,允许key为null*/
└WeakHashMap
4、new 是个操作符,和什么"+","-","="...有一样的地位. (new/delete是C++的运算符)
malloc是个分配内存的函数,供你调用的(malloc与free是C++/C语言的标准库函数)
new是保留字,不需要头文件支持.
malloc需要头文件库函数支持.
new 建立的是一个对象,
malloc分配的是一块内存.
new建立的对象你可以把它当成一个普通的对象,用成员函数访问,不要直接访问它的地址空间
malloc分配的是一块内存区域,就用指针访问好了,而且还可以在里面移动指针.
5、函数库:一组处于可以"拿来就用"状态下的二进制目标代码文件。需要用到函数库中的某个函数时,就可以通过include语句引用对此函数作出声明的头文件。
静态库(windows:*.lib,linux:*.a):编译器和链接程序负责把程序代码和库函数结合在一起成为一个独立的可执行程序。
共享库(windows:*.dll,linux:*.so):静态库的缺点是如果我们在同一时间运行多个程序,而它们又都用着来自同一个函数库中的函数时,内存里就会有许多份同一函数的拷贝,这样会消耗内存和硬盘空间。共享库的链接方式:它本身不在包含函数代码,而是只保存共享代码的调用线索。共享代码是在该程序运行的时候才加入到其中的。当编译好的程序被加载到内存中准备执行的时候,函数的调用线索被解析,程序向共享库发出调用。共享库只有在必要时才被加载到内存。
附:目标文件,二进制文件(windows:*.obj,linux:*.o)
6、采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。比如一个16bit的数 0x1234(类似于十进制数,左边为高位),大端存放顺序是:0x12 0x34;而小端存放顺序则是小的在前面:0x34 0x12
int checkCPU( )
{
{
union w
{
int a;
char b;
} c;
c.a = 1;
return(c.b ==1);
}
}
假设union内存分布从左到右:
如果是大端,则当c.a=1时,内存里存放的顺序为0x01 0x00,则c.b取到的值为1
如果是小端(低位在左),则存放顺序为0x00 0x01,则c.b取到的值为0。
7、主要有两种:拉链法 和 开放地址法。拉链法比较简单,出现冲突的时候直接挂在对应key的链表里。开放地址法处理冲突时有 线性探测法、平方探测法等来寻找冲突元素的存放位置。
8、见各种排序算法。其中当序列基本有序时,快速排序退化为冒泡排序,出现最差情况。
9、C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为: void foo(int x, int y);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。
10、在java中,数组也是对象,因此传递参数时传递的是值,更准确的说法是“引用值”,如果在函数内部改变了数组内容,那么函数返回后原数组内容也会相应改变。但是引用本身不能改变。
11、代码如下:
当i=0 f(n)=0;
当i=1或i=2时,f(n)=1;
i=3开始,执行for循环,保存前一次执行的结果:
int fabonacci(int n){
int i,a,b,tmp;
if(n==0) return 0;
if(n==1||n==2) return 1;
a=1,b=1;
for(i=3;i<=n;i++){
tmp=a+b;
a=b;
b=tmp;
}
return b;
}
12、先将后面那个节点的值赋给当前节点,然后删除下一节点(其实是逻辑上的删除)
13、java中特有的。表示无论该数是否有符号,右移后高位都补0.
14、代码如下。
int getLength(const char *str){
return *str==0?0:getLength(str+1)+1;
}
15、代码如下:
- public void reverse(link* head){
- link *p,*q,*r;
- p=head;
- q=p->next;
- while(q!=NULL){
- r=q->next;
- q->next=p;
- p=q;
- q=r;
- }
- head->next=NULL;
- head=p;
- }
16、面向row的数据,本身是按行存储的,每次取一条记录,不得不将一整条记录拿出来,很多时候也取出了很多无用的属性。
面向column的数据,本身是按列存储的,可以选择某些列进行查询(一次读出一整列),查询起来更快。
17、网络爬虫(数据源)、索引、搜索后排序算法、日志分析(模式)
【附录】
常见题:
c语言中的sizeof问题。
例如:
typedef struct{
int i;
char j;
char k;
double s;
char h;
char m;
}node;
那么sizeof(node)的大小是
(32bit下,假设以4字节对齐):4+1+1+(1+1)+8+1+1+(1+1)=20
(32bit下,假设以8字节对齐):4+1+1+2+8+2+6=24
其中括号内的空间是因为对齐原则而添加进来的。
【注】一般系统系统默认是按照s=8字节对齐,但是实际中,先得到结构体中最宽的字节,如double最宽k=8,然后取min(k,s)来对齐。