首页 > 代码库 > C/C++笔试忍法帖05——数据结构篇

C/C++笔试忍法帖05——数据结构篇

1.写出下列算法的时间复杂度。

(1)冒泡排序; O(n^2)
(2)选择排序; 直接选择排序是O(n^2)
(3)插入排序;直接插入排序是 O(n^2)
(4)快速排序; O(nlog2 n)
(5)堆排序;   O(nlog2 n)
(6)归并排序; O(nlog2 n)


2.编程,请实现一个c语言中类似atoi的函数功能(输入可能包含非数字和空格)

#include <stdio.h>

int isspace(int x) {
	if ((x == 0)||(x == ‘\t‘) || (x == ‘\n‘) || (x == ‘\f‘) || (x == ‘\b‘) || (x == ‘\r‘))
		return 1;
	else
		return 0;
}
int isdigit(int x) {
	if (x <= ‘9‘ && x >= ‘0‘)
		return 1;
	else
		return 0;

}
int atoi(const char *nptr) {
	int c; /* current char */
	int total; /* current total */
	int sign; /* if ‘-‘, then negative, otherwise positive */

	/* skip whitespace */
	while (isspace((int) (unsigned char) *nptr))
		++nptr;

	c = (int) (unsigned char) *nptr++;
	sign = c; /* save sign indication */
	if (c == ‘-‘ || c == ‘+‘)
		c = (int) (unsigned char) *nptr++; /* skip sign */

	total = 0;

	while (isdigit(c)) {
		total = 10 * total + (c - ‘0‘); /* accumulate digit */
		c = (int) (unsigned char) *nptr++; /* get next char */
	}

	if (sign == ‘-‘)
		return -total;
	else
		return total; /* return result, negated if necessary */
}

int main()
{
	char aaa[10] = "20";
	printf("======%d=====\n" , atoi(aaa));
	return 0;
}


3.在排序方法中,关键码比较次数与记录地初始排列无关的是     D
A. Shell排序      B. 归并排序       C. 直接插入排序     D. 选择排序


5. 编写strcat函数(6分)

已知strcat函数的原型是char *strcat (char *strDest, const char *strSrc);

其中strDest 是目的字符串,strSrc 是源字符串。

1)不调用C++/C 的字符串库函数,请编写函数 strcat

答:

VC源码:

char * __cdecl strcat (char * dst, const char * src)

{

char * cp = dst;

while( *cp )

cp++; /* find end of dst */

while( *cp++ = *src++ ) ; /* Copy src to end of dst */

return( dst ); /* return dst */

}

2)strcat能把strSrc 的内容连接到strDest,为什么还要char * 类型的返回值?

答:方便赋值给其他变量

6.用两个栈实现一个队列的功能?要求给出算法和思路!

答 :设2个栈为A,B, 一开始均为空.

    入队:

     将新元素push入栈A;

   出队:

    (1)判断栈B是否为空;

    (2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;

    (3)将栈B的栈顶元素pop出;


7.链表反转
单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题。比如一个链表是这样的:

1->2->3->4->5 
通过反转后成为5->4->3->2->1。
最容易想到的方法遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向的下一个元素,然

后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。源代码如下:
    struct linka { 
    int data; 
    linka* next; 
    }; 
    void reverse(linka*& head) { 
    if(head ==NULL) 
        return; 
    linka *pre, *cur, *ne; 
    pre=head; 
    cur=head->next; 
    while(cur) 
    { 
       ne = cur->next; 
       cur->next = pre; 
       pre = cur; 
       cur = ne; 
    } 
    head->next = NULL; 
    head = pre; 
    } 
还有一种利用递归的方法。这种方法的基本思想是在反转当前节点之前先调用递归函数反转后续节点。

源代码如下。不过这个方法有一个缺点,就是在反转后的最后一个结点会形成一个环,所以必须将函数的

返回的节点的next域置为NULL。因为要改变head指针,所以我用了引用。算法的源代码如下:
    linka* reverse(linka* p,linka*& head) 
    { 
    if(p == NULL || p->next == NULL) 
    { 
       head=p; 
       return p; 
    } 
    else 
    { 
       linka* tmp = reverse(p->next,head); 
       tmp->next = p; 
       return p; 
    } 
    } 


8.编写strcpy函数(10分)

已知strcpy函数的原型是

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

        其中strDest是目的字符串,strSrc是源字符串。

(1)不调用C++/C的字符串库函数,请编写函数 strcpy

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

{

     assert((strDest!=NULL) && (strSrc !=NULL)); // 2分

     char *address = strDest;                    // 2分

     while( (*strDest++ = * strSrc++) != ‘ 0’ )     // 2分

        NULL ;

     return address ;                           // 2分

}

(2)strcpy能把strSrc的内容复制到strDest,为什么还要char * 类型的返回值?

答:为了实现链式表达式。                                               // 2分

例如: int length = strlen( strcpy( strDest, “hello world”) );