面试宝典 程序员面试题精选100题

Rina 分享 时间: 收藏本文

【简介】感谢网友“Rina”参与投稿,下面就是小编给大家分享的面试宝典 程序员面试题精选100题(共8篇),希望大家喜欢!

篇1:面试宝典 程序员面试题精选100题

前言

随着高校的持续扩张,每年应届毕业生的数目都在不断增长,伴随而来的是应届毕业生的就业压力也越来越大。

在这样的背景下,就业变成一个买方市场的趋势越来越明显。为了找到一个称心的工作,绝大多数应届毕业生都必须反复经历简历筛选、电话面试、笔试、面试等环节。在这些环节中,面试无疑起到最为重要的作用,因为通过面试公司能够最直观的了解学生的能力。

为了有效地准备面试,面经这个新兴概念应运而生。笔者在当初找工作阶段也从面经中获益匪浅并最终找到满意的工作。为了方便后来者,笔者花费大量时间收集并整理散落在茫茫网络中的面经。不同行业的面经全然不同,笔者从自身专业出发,着重关注程序员面试的面经,并从精选出若干具有代表性的技术类的面试题展开讨论,希望能给读者带来一些启发。

由于笔者水平有限,给各面试题提供的思路和代码难免会有错误,还请读者批评指正。另外,热忱欢迎读者能够提供更多、更好的面试题,本人将感激不尽。

(01)把二元查找树转变成排序的双向链表

[折叠]

题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。

比如将二元查找树

10

/

6 14

/ /

4 8 12 16

转换成双向链表

4=6=8=10=12=14=16。

分析:本题是微软的面试题。很多与树相关的题目都是用递归的思路来解决,本题也不例外。下面我们用两种不同的递归思路来分析。

思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。最近链接左子链表的最右结点(左子树的最大结点)、当前结点和右子链表的最左结点(右子树的最小结点)。从树的根结点开始递归调整所有结点。

思路二:我们可以中序遍历整棵树。按照这个方式遍历树,比较小的结点先访问。如果我们每访问一个结点,假设之前访问过的结点已经调整成一个排序双向链表,我们再把调整当前结点的指针将其链接到链表的末尾。当所有结点都访问过之后,整棵树也就转换成一个排序双向链表了。

参考代码:

首先我们定义二元查找树结点的数据结构如下:

struct BSTreeNode // a node in the binary search tree

{

int m_nValue; // value of node

BSTreeNode *m_pLeft; // left child of node

BSTreeNode *m_pRight; // right child of node

};

思路一对应的代码:

///////////////////////////////////////////////////////////////////////

// Covert a sub binary-search-tree into a sorted double-linked list

// Input: pNode - the head of the sub tree

// asRight - whether pNode is the right child of its parent

// Output: if asRight is true, return the least node in the sub-tree

// else return the greatest node in the sub-tree

///////////////////////////////////////////////////////////////////////

BSTreeNode* ConvertNode(BSTreeNode* pNode, bool asRight)

{

if(!pNode)

return NULL;

BSTreeNode *pLeft = NULL;

BSTreeNode *pRight = NULL;

// Convert the left sub-tree

if(pNode->m_pLeft)

pLeft = ConvertNode(pNode->m_pLeft, false);

// Connect the greatest node in the left sub-tree to the current node

if(pLeft)

{

pLeft->m_pRight = pNode;

pNode->m_pLeft = pLeft;

}

// Convert the right sub-tree

if(pNode->m_pRight)

pRight = ConvertNode(pNode->m_pRight, true);

// Connect the least node in the right sub-tree to the current node

if(pRight)

{

pNode->m_pRight = pRight;

pRight->m_pLeft = pNode;

}

BSTreeNode *pTemp = pNode;

// If the current node is the right child of its parent,

// return the least node in the tree whose root is the current node

if(asRight)

{

while(pTemp->m_pLeft)

pTemp = pTemp->m_pLeft;

}

// If the current node is the left child of its parent,

// return the greatest node in the tree whose root is the current node

else

{

while(pTemp->m_pRight)

pTemp = pTemp->m_pRight;

}

return pTemp;

}

///////////////////////////////////////////////////////////////////////

// Covert a binary search tree into a sorted double-linked list

// Input: the head of tree

// Output: the head of sorted double-linked list

///////////////////////////////////////////////////////////////////////

BSTreeNode* Convert(BSTreeNode* pHeadOfTree)

{

// As we want to return the head of the sorted double-linked list,

// we set the second parameter to be true

return ConvertNode(pHeadOfTree, true);

}

思路二对应的代码:

///////////////////////////////////////////////////////////////////////

// Covert a sub binary-search-tree into a sorted double-linked list

// Input: pNode - the head of the sub tree

// pLastNodeInList - the tail of the double-linked list

///////////////////////////////////////////////////////////////////////

void ConvertNode(BSTreeNode* pNode, BSTreeNode*& pLastNodeInList)

{

if(pNode == NULL)

return;

BSTreeNode *pCurrent = pNode;

// Convert the left sub-tree

if (pCurrent->m_pLeft != NULL)

ConvertNode(pCurrent->m_pLeft, pLastNodeInList);

// Put the current node into the double-linked list

pCurrent->m_pLeft = pLastNodeInList;

if(pLastNodeInList != NULL)

pLastNodeInList->m_pRight = pCurrent;

pLastNodeInList = pCurrent;

// Convert the right sub-tree

if (pCurrent->m_pRight != NULL)

ConvertNode(pCurrent->m_pRight, pLastNodeInList);

}

///////////////////////////////////////////////////////////////////////

// Covert a binary search tree into a sorted double-linked list

// Input: pHeadOfTree - the head of tree

// Output: the head of sorted double-linked list

///////////////////////////////////////////////////////////////////////

BSTreeNode* Convert_Solution1(BSTreeNode* pHeadOfTree)

{

BSTreeNode *pLastNodeInList = NULL;

ConvertNode(pHeadOfTree, pLastNodeInList);

// Get the head of the double-linked list

BSTreeNode *pHeadOfList = pLastNodeInList;

while(pHeadOfList && pHeadOfList->m_pLeft)

pHeadOfList = pHeadOfList->m_pLeft;

return pHeadOfList;

}

(02)设计包含min函数的栈

[折叠]

题目:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop的时间复杂度都是O(1)。

分析:这是去年google的一道面试题。

我看到这道题目时,第一反应就是每次push一个新元素时,将栈里所有逆序元素排序。这样栈顶元素将是最小元素。但由于不能保证最后push进栈的元素最先出栈,这种思路设计的数据结构已经不是一个栈了。

在栈里添加一个成员变量存放最小元素(或最小元素的位置)。每次push一个新元素进栈的时候,如果该元素比当前的最小元素还要小,则更新最小元素。

乍一看这样思路挺好的。但仔细一想,该思路存在一个重要的问题:如果当前最小元素被pop出去,如何才能得到下一个最小元素?

因此仅仅只添加一个成员变量存放最小元素(或最小元素的位置)是不够的。我们需要一个辅助栈。每次push一个新元素的时候,同时将最小元素(或最小元素的位置。考虑到栈元素的类型可能是复杂的数据结构,用最小元素的位置将能减少空间消耗)push到辅助栈中;每次pop一个元素出栈的时候,同时pop辅助栈。

参考代码:

#include

#include

templateclass CStackWithMin

{

public:

CStackWithMin(void) {}

virtual ~CStackWithMin(void) {}

T& top(void);

const T& top(void) const;

void push(const T& value);

void pop(void);

const T& min(void) const;

private:

T>m_data;// theelements of stack

size_t>m_minIndex;// the indicesof minimum elements

};

// get the last element of mutable stack

templateT& CStackWithMin::top

{

return m_data.back();

}

// get the last element of non-mutable stack

templateconst T& CStackWithMin::top() const

{

return m_data.back();

}

篇2:程序员面试宝典

程序员面试宝典

对于即将成为程序员的应届生,首先需要考虑的是如何选择一个适合自己职业起步的公司,以及根据自己感兴趣的技术确立自己将来的职业方向,对于已经身为程序员的跳槽人员,则需要考虑继续走技术方向还是转型到管理、销售等方面。在求职面试过程中需要什么流程以及需要注意什么细节?

针对初级C/C++工程师职位

所谓的初级C/C++工程师,也就是刚刚踏入C/C++开发领域的初学者,或者说是有过很短经历的C/C++开发者。针对这个职位,下面将会介绍这个职位所需要掌握的知识体系。

面向对象的知识: C++是一个面向对象的开发语言,因此熟悉面向对象对学习C++很有必要。读者要了解:什么是对象、什么是类、什么是封装、什么是多态、什么是继承、什么是抽象类、什么是接口等。读者不但要了解概念,还需要知道这些概念是如何体现的。例如,类和对象有什么区别?类是如何封装的?

C/C++语法:如果读者已经有了开发经验,那对于学习C/C++语法来讲比较容易,

如果你有C++等面向对象语言的'开发经验,那么只需简单的翻看介绍C/C++的相关书籍。如果你是新手,那么就好好研究一本有关C/C++初级教程之类的书。学习了C/C++语法,加上面向对象的知识,相信读者可以写出来比较好的C/C++代码。如果再抽出时间熟悉一下C/C++编程规范,那么代码的水平就会比较正规了。

数据库知识:作为一名初级C++开发工程师,必须要清楚如何使用数据库进行一些简单的开发工作,这是一些应用软件开发的基础。

开发工具:读者都知道,开发工具可以帮助更好更快地开发,因此熟悉几种开发工具很有必要。目前C/C++的开发工具比较流行的有Turbo C和Visual C++ 6.0等。

掌握了以上的知识,另外再加上少许的开发经验,就可以称得上是一名基本合格的初级C/C++开发工程师。所有招聘公司对于初级程序员的要求并不高,但基础知识一定要扎实,如果你连开发工具都不会使用,那如何能迅速提高学习水平呢?

针对中、高级C/C++开发工程师职位

所谓的中、高级C/C++开发工程师,也就是有了几年的开发经验和实战经验的开发人员。针对这个职位,

篇3:程序员面试宝典

作 者:欧立奇,刘洋,段韬编

出 版 社:电子工业出版社 时 间:-11-1

原 价:39.80元

当当网最低价格:29.90元

卓越网最低价格:元

去当当网免费阅读,购买本书

程序员面试宝典(第二版) 欧立奇,刘洋,段韬编内容简介:

本书是《程序员面试宝典》的第二版,在保留第一版的数据结构、面向对象、程序设计等主干的基础上,使用各大IT公司及相关企业-的最新面试题替换和补充原内容,以反映自第一版以来近2年的时间所发生的变化。

本书取材于各大公司面试真题(笔试、口试、电话面试、英语面试,以及逻辑测试和智商测试),详细分析了应聘程序员(含网络、测试等)职位的常见考点。本书不仅对传统的C系语言考点做了详尽解说,还根据外企出题最新特点,新增加了对友元、Static、图形/音频、树、栈、ERP等问题的深入讲解。最后本书着力讲述了如何进行英语面试和电话面试,并对求职中签约、毁约的注意事项及群体面试进行了解析。本书的面试题除了有详细解析和回答外,对相关知识点还有扩展说明。希望真正做到由点成线,举一反三,对读者从求职就业到提升计算机专业知识都有显著帮助。

本书适合计算机相关专业应届毕业生阅读,也适合作为正在应聘软件行业的相关就业人员和计算机爱好者的参考书。

当当网用户妮妮90:

感觉书的质量不是很好,小的印刷错误也不少不过书的内容还是不错的

当当网用户玛莉梦菲:

不知道是配送问题,还是别的,新书上都有扎的洞了,质量太不行了

当当网用户落英缓缓:

不过这本书定位挺高的,面试题很丰富!

这篇文章希望能解决程序员面试宝典(第二版)写得好不好,读者读后感怎么样,网上哪里有卖,最低价格是多少钱,网上免费阅读地址,值不值得买等问题。

[程序员面试宝典]

篇4:程序员面试宝典bolg

托普集团程序员面试试

一、选择题(每题1分,共20分)1.下列那种语言是面向对象的(C)

A. C B. PASCAL C. C++ D. FORTRAN77

2.在 Windows9x 下,可以进入 MS-D0S 方式。当在 DOS 提示符下键入 ( B ) 命令后,系统将退出 MS-DOS方式,返回到 WIndows 方式。 A. CLOSE B. EXIT C. QUIT D. RETURN

3.下面哪些是面向对象的基本特性:( ABC)A 多态 B 继承 C 封装 D 接口

4.在C++中经常要进行异常处理,下面哪些是异常处理常用到的关键词:(ABC)

A try B catch C throw D break E contiue

5.数据库技术中的“脏数据',是指(C)的数据。A.错误B.回返C.未提交D.未提交的随后又被撤消

6.TCP/IP是一种(A,B)A.标准 B.协议 C.语言 D.算法

7. 下面有关计算机操作系统的叙述中,不正确的是(B ) A 操作系统属于系统软件 B 操作系统只负责管理内存储器,而不管理外存储器 C UNIX 是一种操作系统 D 计算机的处理器、内存等硬件资源也由操作系统管理

8.微机上操作系统的作用是( D) A 解释执行源程序 B 编译源程序

C 进行编码转换 D 控制和管理系统资源

9.下列存储器中存取速度最快的是( A) A 内存 B 硬盘 C 光盘 D 软盘

10.在计算机中,―个字节是由多少个二进制位组成的(B ) A. 4 B. 8 C. 16 D. 24

11. 存储16×16点阵的一个汉字信息,需要的字节数为( A )A 32 B 64 C 128 D 256

12. 以下选项中合法的字符常量是(BC)A.“B” B. '10' C. 68 D. D

13. 假定x和y为double型,则表达式x=2,y=x+3/2的值是(D)A. 3.500000 B. 3 C. 2.000000 D. 3.000000

14. 以下合法的赋值语句是(BCD)//In C++ ,choice D also is correct, but in C language, D is wrong.

A. x=y=100 B. d--; C. x+y; D. c=int(a+b);

15. 设正x、y均为整型变量,且x=10 y=3,则以下语句pprintf(“%d,%d ”,x--,--y); 的输出结果是(D)

A.10,3 B. 9,3 C. 9,2 D.10,2

16. x、y、z被定义为int型变量,若从键盘给x、y、z输入数据,正确的输入语句是(B)

A .INPUT x、y、z; B. scanf(“%d%d%d”,&x,&y,&z);C. scanf(“%d%d%d”,x,y,z); D. read(“%d%d%d”,&x,&y,&z);

17.以下数组定义中不正确的是(D)A) int a[2][3]; B) int b[][3]={0,1,2,3};C) int c[100][100]={0}; D) int d[3][]={{1,2},{1,2,3},{1,2,3,4}};

18. 以下程序的输出结果是(A)main{ int a[4][4]={{1,3,5},{2,4,6},{3,5,7}};

printf(“%d%d%d%d ”,a[0][3],a[1][2],a[2][1],a[3][0];

}A) 0650 B) 1470 C) 5430 D) 输出值不定

19 以下程序的输出结果是(B)main(){char st[20]= “hello ”;printf(%d %d “,strlen(st),sizeof(st));

}A) 9 9 B) 5 20 C) 13 20 D) 20 20

20. 当调用Windows API函数InvalidateRect,将会产生什么消息(A)A:WM_PAINT B:WM_CREATE C:WM_NCHITTEST D:WM_SETFOCUS

二、填空题(每题3分,共30分)

1.请列举当前一些当前流行的数据库引擎,SQL SERVER,ORACLE,BDE,Microsoft Jet。

2.为了将当前盘当前目录中的所有文本文件(扩展名为.TXT)的内容打印输出,正确的单条DOS命令为COPY *.TXT PRN。

3. 计算机网络分为局域网和广域网,因特网属于广域网。

4. 设y是int型变量,请写出判断y为奇效的关系表达y%2!=0。

5. 设有以下程序:main(){ int n1,n2;scanf(”%d“,&n2);while(n2!=0){ n1=n2%10;n2=n2/10;printf(”%d“,n1);}}

程序运行后,如果从键盘上输入1298;则输出结果为8921。

6.以下程序运行后的输出结果是:9876 876

main(){ char s[ ]=”9876“,*p;for ( p=s ; p

7.以下函数的功能是:求x的y次方,请填空。double fun( double x, int y){ int i;double z;for(i=1, z=x; i

8.以下程序段打开文件后,先利用fseek函数将文件位置指针定位在文件末尾,然后调用ftell函数返回当前文件位置指针的具体位置,从而确定文件长度,请填空。FILE *myf; long f1;myf= fopen (”test.t“,”rb“);

fseek(myf,0,SEEK_END); f1=ftell(myf);fclose(myf);printf(”%d “,f1);

9. 以下程序输出的最后一个值是120。

int ff(int n){ static int f=l;f=f*n;return f;}main(){ int i;for(I=1;I<=5;I++ printf(”%d “,ff(i));)

10. 以下程序运行后的输出结果是52 main(){ int i=10, j=0;do{ j=j+i; i--;while(i>2);printf(”%d ",j);}

三、判断题(每题2分,共20分)

1:动态链结库不能静态调用。 错误

2:UDP是面向无连接的网络连接 正确

3:ASP是一种数据库引擎 错误

4:队列是先进后出。 错误

5:Weblogic是分布式应用服务器。 正确

6:TCP,UDP都是传输层的协议。 正确

7: 两个线程不能共存于同一地址空间 错误

8: JAVA是一种跨平台的开发工具 正确

9.在WINDOWS操作系统中对外设是以文件的方式进行管理 正确

10. 虚拟内存实际是创建在硬盘上的 正确

四、问答题(每题10分,共30分)

1.写出从数据库表Custom中查询No、Name、Num1、Num2并将Name以姓名显示、计算出的和以总和显示的SQL。SELECT No , Name AS ‘姓名’ ,Num1 ,Num2,(Num1+Num2) AS ‘总和’

FROM Custom

何为“事务处理”,谈谈你对它的理解。事务处理是指一个单元的工作,这些工作要么全做,要么全部不做。作为一个逻辑单元,必须具备四个属性:自动性、一致性、独立性和持久性。自动性是指事务必须是一个自动的单元工作,要么执行全部数据的修改,要么全部数据的修改都不执行。一致性是指当事务完成时,必须使所有数据都具有一致的状态。在关系型数据库中,所有的规则必须应用到事务的修改上,以便维护所有数据的完整性。所有的内部数据结构,在事务结束之后,必须保证正确。独立性是指并行事务的修改必须与其他并行事务的修改相互独立。一个事务看到的数据要么是另外一个事务修改这些事务之前的状态,要么是第二个事务已经修改完成的数据,但是这个事务不能看到正在修改的数据。

3. 常用的数据结构有哪些?请枚举一些。(不少于5个)链表、堆栈、二叉树、队列、图、堆,集合。

4. 什么是OOP?什么是类?请对比类和对象实例之间的关系。OOP是Object_oriented Programming(面向对象编程)的缩写。这主要是为了区别于以前的面向过程的程序设计!指的是用对象的观点来组织与构建系统,它综合了功能抽象和数据抽象,这样可以减少数据之间的耦合性和代码的出错几率。使用面向对象编程技术可以使得软件开发者按照现实世界里人们思考问题的模式编写代码,可以让软件开发者更好地利用代码直接表达现实中存在的对象,将问题空间直接映射到解空间!类:即class 在面向对象的程序设计中,专门用“类”来表示用户定义的抽象数据类型(user_defined abstract type)。它将具有相同状态、操作和访问机制的多个对象进行了抽象。类具有继承、数据隐藏和多态三种主要特性。利用类的这三种特性可以更好地表示现实世界中事物。类是同一类对象实例的共性的抽象,对象是类的实例化。对象通常作为计算机模拟思维,表示真实世界的抽象,一个对象就像一个软件模块,可以为用户提供一系列的服务---可以改变对象的状态、测试、传递消息等。类定义了对象的实现细节或数据结构。类是静态的,对象是动态的,对象可以看作是运行中的类。类负责产生对象,可以将类当成生产对象的工厂(Object factory).

篇5:c++程序员面试宝典

试题1:

void test1()

{

char string[10];

char* str1 = “0123456789″;

strcpy( string, str1 );

}

试题2:

void test2()

{

char string[10], str1[10];

int i;

for(i=0; i<10; i++)

{

str1[i] = ’a’;

}

strcpy( string, str1 );

}

试题3:

void test3(char* str1)

{

char string[10];

if( strlen( str1 ) <= 10 )

{

strcpy( string, str1 );

}

}

解答:

试题1字符串str1需要11个字节才能存放下(包括末尾的’’),而string只有10个字节的空间,strcpy会导致数组越界;

对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string,

str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10

分;

对试题3,if(strlen(str1) <= 10)应改为if(strlen(str1) <

10),因为strlen的结果未统计’’所占用的1个字节。

剖析:

考查对基本功的掌握:

(1)字符串以’’结尾;

(2)对数组越界把握的敏感度;

(3)库函数strcpy的工作方式,如果编写一个标准strcpy函数的总分值为10,下面给出几个不同得分的答案:

2分

void strcpy( char *strDest, char *strSrc )

{

while( (*strDest++ = * strSrc++) != ‘’ );

}

4分

void strcpy( char *strDest, const char *strSrc )

//将源字符串加const,表明其为输入参数,加2分

{

while( (*strDest++ = * strSrc++) != ‘’ );

}

7分

void strcpy(char *strDest, const char *strSrc)

{

//对源地址和目的地址加非0断言,加3分

assert( (strDest != NULL) && (strSrc != NULL) );

while( (*strDest++ = * strSrc++) != ‘’ );

}

10分

//为了实现链式操作,将目的地址返回,加3分!

char * strcpy( char *strDest, const char *strSrc )

{

assert( (strDest != NULL) && (strSrc != NULL) );

char *address = strDest;

while( (*strDest++ = * strSrc++) != ‘’ );

return address;

}

从2分到10分的几个答案我们可以清楚的看到,小小的strcpy竟然暗藏着这么多玄机,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!

(4)对strlen的掌握,它没有包括字符串末尾的’’。

读者看了不同分值的strcpy版本,应该也可以写出一个10分的strlen函数了,完美的版本为:

int strlen( const char *str ) //输入参数const

{

assert( strt != NULL ); //断言字符串地址非0

int len;

while( (*str++) != ’’ )

{

len++;

}

return len;

}

试题4:

void GetMemory( char *p )

{

p = (char *) malloc( 100 );

}

void Test( void )

{

char *str = NULL;

GetMemory( str );

strcpy( str, “hello world” );

printf( str );

}

试题5:

char *GetMemory( void )

{

char p[] = “hello world”;

return p;

}

void Test( void )

{

char *str = NULL;

str = GetMemory();

printf( str );

}

试题6:

void GetMemory( char **p, int num )

{

*p = (char *) malloc( num );

}

void Test( void )

{

char *str = NULL;

GetMemory( &str, 100 );

strcpy( str, “hello” );

printf( str );

}

试题7:

void Test( void )

{

char *str = (char *) malloc( 100 );

strcpy( str, “hello” );

free( str );

… //省略的其它语句

}

解答:

试题4传入中GetMemory( char *p

)函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入形参的值,执行完

char *str = NULL;

GetMemory( str );

后的str仍然为NULL;

试题5中

char p[] = “hello world”;

return p;

的p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。这是许多程序员常犯的错误,其根源在于不理解变量的生存期。

试题6的GetMemory避免了试题4的问题,传入GetMemory的参数为字符串指针的指针,但是在GetMemory中执行申请内存及赋值语句

*p = (char *) malloc( num );

后未判断内存是否申请成功,应加上:

if ( *p == NULL )

{

…//进行申请内存失败处理

}

试题7存在与试题6同样的问题,在执行

char *str = (char *) malloc(100);

后未进行内存是否申请成功的判断;另外,在free(str)后未置str为空,导致可能变成一个“野”指针,应加上:

str = NULL;

试题6的Test函数中也未对malloc的内存进行释放。

剖析:

试题4~7考查面试者对内存操作的理解程度,基本功扎实的面试者一般都能正确的回答其中50~60的错误。但是要完全解答正确,却也绝非易事。

对内存操作的考查主要集中在:

(1)指针的理解;

(2)变量的生存期及作用范围;

(3)良好的动态内存申请和释放习惯。

再看看下面的一段程序有什么错误:

swap( int* p1,int* p2 )

{

int *p;

*p = *p1;

*p1 = *p2;

*p2 = *p;

}

在swap函数中,p是一个“野”指针,有可能指向系统区,导致程序运行的崩溃。在VC++中DEBUG运行时提示错误“Access

Violation”。该程序应该改为:

swap( int* p1,int* p2 )

{

int p;

p = *p1;

*p1 = *p2;

*p2 = p;

}

[c++程序员面试宝典]

篇6:程序员面试宝典java

map,set,list,等JAVA中集合解析(了解)

在JAVA的util包中有两个所有集合的父接口Collection和Map,它们的父子关系:

java.util

+Collection 这个接口extends自 --java.lang.Iterable接口

+List 接口

-ArrayList 类

-LinkedList 类

-Vector 类 此类是实现同步的

+Queue 接口

+不常用,在此不表.

+Set 接口

+SortedSet 接口

-TreeSet 类

-HashSet

+Map 接口

-HashMap 类 (除了不同步和允许使用 null 键/值之外,与 Hashtable 大致相同.)

-Hashtable 类 此类是实现同步的,不允许使用 null 键值

+SortedMap 接口

-TreeMap 类

以下对众多接口和类的简单说明:首先不能不先说一下数组(Array)

一、Array , Arrays

Java所有“存储及随机访问一连串对象”的做法,array是最有效率的一种。

1、

效率高,但容量固定且无法动态改变。

array还有一个缺点是,无法判断其中实际存有多少元素,length只是告诉我们array的容量。

2、Java中有一个Arrays类,专门用来操作array。

arrays中拥有一组static函数,

equals:比较两个array是否相等。array拥有相同元素个数,且所有对应元素两两相等。

fill():将值填入array中。

sort():用来对array进行排序。

binarySearch():在排好序的array中寻找元素。

System.arraycopy():array的复制。

二、Collection , Map

若撰写程序时不知道究竟需要多少对象,需要在空间不足时自动扩增容量,则需要使用容器类库,array不适用。

1、Collection 和 Map 的区别

容器内每个为之所存储的元素个数不同。

Collection类型者,每个位置只有一个元素。

Map类型者,持有 key-value pair,像个小型数据库。

2、Java2容器类类库的用途是“保存对象”,它分为两类,各自旗下的子类关系

Collection

--List:将以特定次序存储元素。所以取出来的顺序可能和放入顺序不同。

--ArrayList / LinkedList / Vector

--Set : 不能含有重复的元素

--HashSet /TreeSet

Map

--HashMap

--HashTable

--TreeMap

Map----一组成对的“键值对”对象,即其元素是成对的对象,最典型的应用就是数据字典,并且还有其它广泛的应用。另外,Map可以返回其所有键组成的Set和其所有值组成的Collection,或其键值对组成的Set,并且还可以像数组一样扩展多维Map,只要让Map中键值对的每个“值”是一个Map即可。

Collection下 1.迭代器

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

Java中的Iterator功能比较简单,并且只能单向移动:

(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

(2) 使用next()获得序列中的下一个元素。

(3) 使用hasNext()检查序列中是否还有元素。

(4) 使用remove()将迭代器新返回的元素删除。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

2.List的功能方法

List(interface): 次序是List最重要的特点;它确保维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(只推荐LinkedList使用)。一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插入和删除元素。

ArrayList: 由数组实现的List。它允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。ListIterator只应该用来由后向前遍历ArrayList,而不是用来插入和删除元素,因为这比LinkedList开销要大很多。

LinkedList: 由列表实现的List。对顺序访问进行了优化,向List中间插入与删除得开销不大,随机访问则相对较慢(可用ArrayList代替)。它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast(),这些方法(没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。

3.Set的功能方法

Set(interface): 存入Set的每个元素必须是唯一的,这也是与List不同的,因为Set不保存重复元素。加入Set的Object必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。

HashSet: HashSet能快速定位一个元素,存入HashSet的对象必须定义hashCode()。

TreeSet: 保持次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。

LinkedHashSet: 具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。

HashSet采用散列函数对元素进行排序,这是专门为快速查询而设计的;TreeSet采用红黑树的数据结构进行排序元素;LinkedHashSet内部使用散列以加快查询速度,同时使用链表维护元素的次序,使得看起来元素是以插入的顺序保存的。需要注意的是,生成自己的类时,Set需要维护元素的存储顺序,因此要实现Comparable接口并定义compareTo()方法。

3、其他特征

* List,Set,Map将持有对象一律视为Object型别。

* Collection、List、Set、Map都是接口,不能实例化。

继承自它们的 ArrayList, Vector, HashTable, HashMap是具象class,这些才可被实例化。

* vector容器确切知道它所持有的对象隶属什么型别。vector不进行边界检查。

三、Collections

Collections是针对集合类的一个帮助类。提供了一系列静态方法实现对各种集合的搜索、排序、线程完全化等操作。

相当于对Array进行类似操作的类Arrays。

如,Collections.max(Collection coll); 取coll中最大的元素。

Collections.sort(List list); 对list中元素排序

四、如何选择?

1、容器类和Array的区别、择取

* 容器类仅能持有对象引用(指向对象的指针),而不是将对象信息copy一份至数列某位置。

* 一旦将对象置入容器内,便损失了该对象的型别信息。

2、

* 在各种Lists中,最好的做法是以ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList();

Vector总是比ArrayList慢,所以要尽量避免使用。

* 在各种Sets中,HashSet通常优于HashTree(插入、查找)。只有当需要产生一个经过排序的序列,才用TreeSet。

HashTree存在的唯一理由:能够维护其内元素的排序状态。

* 在各种Maps中

HashMap用于快速查找。

* 当元素个数固定,用Array,因为Array效率是最高的。

结论:最常用的是ArrayList,HashSet,HashMap,Array。而且,我们也会发现一个规律,用TreeXXX都是排序的。

注意:

1、Collection没有get()方法来取得某个元素。只能通过iterator()遍历元素。

2、Set和Collection拥有一模一样的接口。

3、List,可以通过get()方法来一次取出一个元素。使用数字来选择一堆对象中的一个,get(0)...。(add/get)

4、一般使用ArrayList。用LinkedList构造堆栈stack、队列queue。

5、Map用 put(k,v) / get(k),还可以使用containsKey()/containsValue()来检查其中是否含有某个key/value。

HashMap会利用对象的hashCode来快速找到key。

* hashing

哈希码就是将对象的信息经过一些转变形成一个独一无二的int值,这个值存储在一个array中。

我们都知道所有存储结构中,array查找速度是最快的。所以,可以加速查找。

发生碰撞时,让array指向多个values。即,数组每个位置上又生成一个表。

6、Map中元素,可以将key序列、value序列单独抽取出来。

使用keySet()抽取key序列,将map中的所有keys生成一个Set。

使用values()抽取value序列,将map中的所有values生成一个Collection。

为什么一个生成Set,一个生成Collection?那是因为,key总是独一无二的,value允许重复。

===List接口对Collection进行了简单的扩充,它的具体实现类常用的有ArrayList和LinkedList。你可以将任何东西放到一个List容器中,并在需要时从中取出。ArrayList从其命名中可以看出它是一种类似数组的形式进行存储,因此它的随机访问速度极快,而LinkedList的内部实现是链表,它适合于在链表中间需要频繁进行插入和删除操作。在具体应用时可以根据需要自由选择。前面说的Iterator只能对容器进行向前遍历,而ListIterator则继承了Iterator的思想,并提供了对List进行双向遍历的方法。

Set接口也是Collection的一种扩展,而与List不同的时,在Set中的对象元素不能重复,也就是说你不能把同样的东西两次放入同一个Set容器中。它的常用具体实现有HashSet和TreeSet类。HashSet能快速定位一个元素,但是你放到HashSet中的对象需要实现hashCode()方法,它使用了前面说过的哈希码的算法。而TreeSet则将放入其中的元素按序存放,这就要求你放入其中的对象是可排序的,这就用到了集合框架提供的另外两个实用类Comparable和Comparator。一个类是可排序的,它就应该实现Comparable接口。有时多个类具有相同的排序算法,那就不需要在每分别重复定义相同的排序算法,只要实现Comparator接口即可。集合框架中还有两个很实用的公用类:Collections和Arrays。Collections提供了对一个Collection容器进行诸如排序、复制、查找和填充

[程序员面试宝典java]

篇7:java程序员面试宝典

有一种说法是面试时交流的过程其实就是一个和人打交道的过程。那么,想成为一个java程序员,在面试之前,想一下你所面对的人即HR,和他做一次心灵上的交流,对自己也会有心态上和能力上的提升。

java程序员面试宝典--把自己当作英语天才

面试题目全部为英文,而且涉及到的知识面极广,一般来说,只有重点大学中品学兼优的在校学生才能搞定,不过鄙人以为大多数这样的人都去读研了。这样的题目通常出现在注册资产在一亿以上的公司,他们要是成长性好的员工,这是无可厚非的事情。不过他们认为工作了一年以上的程序员也能轻松搞定,至少有部分人能搞。所以当你踌躇满志的去应聘之前,请看看你的实力如何(过六级或者四级680分以上,专业课平均分80以上者可以一试)。

java程序员面试宝典--把自己视为java语言的高手

现在网上流行的大公司面试题可能有些人已经看过了,我用java将近两年了,自认为资质不弱常人,但那样的题目拿到手之后的感觉就是憋气。很多地方只是有个模糊的概念,回答不完全,查阅资料之后方能答上。或许我的基础还有些薄弱,不过当我试着以试题上的题目与面试我的人“讨论”时发现,他知道的也就是这一题的答案而已。

java程序员面试宝典--把自己当作编译器

考试题目大都是一些读程序写结果,或者找错误之类的,不过很多都是编译特例,如果给你个IDE,你肯定是轻松搞定,但你没有那样的机会,回答不出来说明你实际操作经验不足(别人就那么认为的)。虽然这也的确是程序员应该掌握的东西,但是这样似乎有些以偏概全了。平时忙着做项目,有空的时候学习新技术,谁会有那种闲夫去研究java原来可以这样运行的。

java程序员面试宝典--一些经验的东西对面试很重要

一份十页的卷子,他只需要看一两分钟就ok了,然后过来和你谈。询问的主要是过去做过什么项目,当然你说的越多越好(不能太夸张)。这样的面试一般是经理或者老板出马,因为你回答的东西他们看不懂,所以就懒得看了。如果你做过项目,那么适当的,含蓄的夸张点你所做过的东西,态度要好,同时要求的工资不能太高,市场价就可以了。对于那些没有工作经验或者经验较少的人,我只能报以深切的同情。不过如果你基础好,糊弄这样的老板应该没有什么问题。

总结:建议读者面试时不能自吹自擂,也不能心虚胆怯,要实实在在,一是一,二是二,把自己的优势和劣势都陈述出来,让考官定夺。当然,要多说优势少说劣势,但绝不能只说优势不说劣势,有人就是因为每次面试都主动述说一两条自己的劣势赢得考官的好感而面试成功的。

篇8:程序员面试宝典 java

1、 什么是Java集合API

Java集合框架API是用来表示和操作集合的统一框架,它包含接口、实现类、以及帮助程序员完成一些编程的算法。简言之,API在上层完成以下几件事:

● 编程更加省力,提高城程序速度和代码质量

● 非关联的API提高互操作性

● 节省学习使用新API成本

● 节省设计新API的时间

● 鼓励、促进软件重用

具体来说,有6个集合接口,最基本的是Collection接口,由三个接口Set、List、SortedSet继承,另外两个接口是Map、SortedMap,这两个接口不继承Collection,表示映射而不是真正的集合。

2、 什么是Iterator

一些集合类提供了内容遍历的功能,通过java.util.Iterator接口。这些接口允许遍历对象的集合。依次操作每个元素对象。当使用Iterators时,在获得Iterator的时候包含一个集合快照。通常在遍历一个Iterator的时候不建议修改集合本省。

3、 Iterator与ListIterator有什么区别?

Iterator:只能正向遍历集合,适用于获取移除元素。ListIerator:继承Iterator,可以双向列表的遍历,同样支持元素的修改。

4、 什么是HaspMap和Map?

Map是接口,Java 集合框架中一部分,用于存储键值对,HashMap是用哈希算法实现Map的类。

5、 HashMap与HashTable有什么区别?对比Hashtable VS HashMap

两者都是用key-value方式获取数据。Hashtable是原始集合类之一(也称作遗留类)。HashMap作为新集合框架的一部分在Java2的1.2版本中加入。它们之间有一下区别:

● HashMap和Hashtable大致是等同的,除了非同步和空值(HashMap允许null值作为key和value,而Hashtable不可以)。

● HashMap没法保证映射的顺序一直不变,但是作为HashMap的子类LinkedHashMap,如果想要预知的顺序迭代(默认按照插入顺序),你可以很轻易的置换为HashMap,如果使用Hashtable就没那么容易了。

● HashMap不是同步的,而Hashtable是同步的。

● 迭代HashMap采用快速失败机制,而Hashtable不是,所以这是设计的考虑点。

6、 在Hashtable上下文中同步是什么意思?

同步意味着在一个时间点只能有一个线程可以修改哈希表,任何线程在执行hashtable的更新操作前需要获取对象锁,其他线程等待锁的释放。

7、 什么叫做快速失败特性

从高级别层次来说快速失败是一个系统或软件对于其故障做出的响应。一个快速失败系统设计用来即时报告可能会导致失败的任何故障情况,它通常用来停止正常的操作而不是尝试继续做可能有缺陷的工作。当有问题发生时,快速失败系统即时可见地发错错误告警。在Java中,快速失败与iterators有关。如果一个iterator在集合对象上创建了,其它线程欲“结构化”的修改该集合对象,并发修改异常 (ConcurrentModificationException) 抛出。

8、 怎样使Hashmap同步?

HashMap可以通过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。

9、 什么时候使用Hashtable,什么时候使用HashMap

基本的不同点是Hashtable同步HashMap不是的,所以无论什么时候有多个线程访问相同实例的可能时,就应该使用Hashtable,反之使用HashMap。非线程安全的数据结构能带来更好的性能。

如果在将来有一种可能―你需要按顺序获得键值对的方案时,HashMap是一个很好的选择,因为有HashMap的一个子类LinkedHashMap。所以如果你想可预测的按顺序迭代(默认按插入的顺序),你可以很方便用LinkedHashMap替换HashMap。反观要是使用的Hashtable就没那么简单了。同时如果有多个线程访问HashMap,Collections.synchronizedMap()可以代替,总的来说HashMap更灵活。

10、为什么Vector类认为是废弃的或者是非官方地不推荐使用?或者说为什么我们应该一直使用ArrayList而不是Vector

你应该使用ArrayList而不是Vector是因为默认情况下你是非同步访问的,Vector同步了每个方法,你几乎从不要那样做,通常有想要同步的是整个操作序列。同步单个的操作也不安全(如果你迭代一个Vector,你还是要加锁,以避免其它线程在同一时刻改变集合).而且效率更慢。当然同样有锁的开销即使你不需要,这是个很糟糕的方法在默认情况下同步访问。你可以一直使用Collections.sychronizedList来装饰一个集合。

事实上Vector结合了“可变数组”的集合和同步每个操作的实现。这是另外一个设计上的缺陷。Vector还有些遗留的方法在枚举和元素获取的方法,这些方法不同于List接口,如果这些方法在代码中程序员更趋向于想用它。尽管枚举速度更快,但是他们不能检查如果集合在迭代的时候修改了,这样将导致问题。尽管以上诸多原因,oracle也从没宣称过要废弃Vector.

[程序员面试宝典 java]

相关专题 程序员宝典