搜狗2012.9.23校園招聘會筆試題

轉載請標明出處,原文地址:http://blog.csdn.net/hackbuteer1/article/details/8016173
C/C++類
1、以下程序的輸出是(12
class Base
{
public:
	Base(int j) : i(j) {  } 
	virtual ~Base() {  }
	void func1()
	{
		i *= 10;
		func2();
	}
	int getValue()
	{
		return i;
	}
protected:
	virtual void func2()
	{
		i++;
	}
protected:
	int i;
};

class Child : public Base
{
public:
	Child(int j) : Base(j) {  }
	void func1()
	{
		i *= 100;
		func2();
	}
protected:
	void func2()
	{
		i += 2;
	}
};

int main(void)
{
	Base *pb = new Child(1);
	pb->func1();
	cout<<pb->getValue()<<endl;
	delete pb;
	
	return 0;
}
2、請問程序的輸出結果是(30)
#define DOUBLE(x) x+x // x*2
int i = DOUBLE(5)*5;
cout<<i<<endl;
3、寫出一下程序的輸出(死循環

int main(void)
{
	char num;
	for(num = 0; num < 255; )
		num += num;
	printf("%d\n",num);
	return 0;
}
4、程序出錯在什麼階段?()
int main(void)
{
	http://www.sogou.com
	cout<<"welcome to sogou"<<endl;
	
	return 0;
}
A、編譯階段出錯     B、運行階段出錯     C、編譯和運行都出錯    D、程序運行正常
因爲http://www.sogou.com中//後面是註釋,前面的http:是標籤(類似於goto語句中的標籤)。(這個題目碉堡了)

5、下面程序執行結果爲【說明:X86_64環境】(D)

int main(void)
{
	int a[4][4] = {
		          {1,2,3,4},
				  {50,60,70,80},
				  {900,1000,1100,1200},
				  {13000,14000,15000,16000} };
	int (*p1)[4] = a;
	int (*p2)[4] = &a[0];
	int *p3 = &a[0][0];
	printf("%d %d %d %d\n",*(*(a+1)-1),*(*(p1+3)-2)+1,*(*(p2-1)+16)+2,*(p3+sizeof(p1)-3));
	
	return 0;
}
A、16000 1101  13002 2
B、4  2  3  60
C、16000  2  3  2
D、4  1101  13002  60
p1爲指向一維數組的指針,所以a + 1指向{50,60,70,80}這一維的地址。減一則爲4的地址;同理第二個輸出1101。同理,由於數組的列是4,所以*(p2 - 1) + 16就相當於*(p2) + 12,所以第三個輸出13002。
第四個由於p1是指針,所以sizeof(p1)爲8(68位的系統),所以第四個輸出60。

6、在32位操作系統gcc編譯器環境下,下面的程序的運行結果是(A)

class A
{
public:
	int b;
	char c;
	virtual void print()
	{
		cout<<"this is father's function!"<<endl;
	}
};

class B : A
{
public:
	virtual void print()
	{
		cout<<"this is children's function!"<<endl;
	}
};
int main(void)
{
	cout<<sizeof(A)<<"  "<<sizeof(A)<<endl;
	
	return 0;
}
A、12  12
B、8  8
C、9  9
D、12  16
7、以下哪些做法是不正確或者應該極力避免的:【多選】(ACD)
A、構造函數聲明爲虛函數
B、派生關係中的基類析構函數聲明爲虛函數
C、構造函數調用虛函數
D、析構函數調用虛函數
8、關於C++標準模板庫,下列說法錯誤的有哪些:【多選】(AD)
A、std::auto_ptr<Class A>類型的對象,可以放到std::vector<std::auto_ptr<Class A>>容器中
B、std::shared_ptr<Class A>類型的對象,可以放到std::vector<std::shared_ptr<Class A>>容器中
C、對於複雜類型T的對象tObj,++tObj和tObj++的執行效率相比,前者更高
D、採用new操作符創建對象時,如果沒有足夠內存空間而導致創建失敗,則new操作符會返回NULL
A中auto是給別人東西而自己沒有了。所以不符合vector的要求。而B可以。C不解釋。new在失敗後拋出標準異常std::bad_alloc而不是返回NULL。

9、有如下幾個類和函數定義,選項中描述正確的是:【多選】(B)

class A
{
public:
	virtual void foo()   {	}
};

class B
{
public:
	virtual void foo()   {	}
};

class C : public A , public B
{
public:
	virtual void foo()   {	}
};

void bar1(A *pa)
{
	B *pc = dynamic_cast<B*>(pa);
}

void bar2(A *pa)
{
	B *pc = static_cast<B*>(pa);
}

void bar3()
{
	C c;
	A *pa = &c;
	B *pb = static_cast<B*>(static_cast<C*>(pa));
}
A、bar1無法通過編譯
B、bar2無法通過編譯
C、bar3無法通過編譯
D、bar1可以正常運行,但是採用了錯誤的cast方法
選B。dynamic_cast是在運行時遍歷繼承樹,所以,在編譯時不會報錯。但是因爲A和B沒啥關係,所以運行時報錯(所以A和D都是錯誤的)。static_cast:編譯器隱式執行的任何類型轉換都可由它顯示完成。其中對於:(1)基本類型。如可以將int轉換爲double(編譯器會執行隱式轉換),但是不能將int*用它轉換到double*(沒有此隱式轉換)。(2)對於用戶自定義類型,如果兩個類無關,則會出錯(所以B正確),如果存在繼承關係,則可以在基類和派生類之間進行任何轉型,在編譯期間不會出錯。所以bar3可以通過編譯(C選項是錯誤的)。

10、在Intel CPU上,以下多線程對int型變量x的操作,哪幾個不是原子操作,假定變量的地址都是對齊的。【多選】(ABC)
A、x = y   B、x++     C、++x     D、x = 1
看下在VC++6.0下的彙編命令即可:從圖可以看出本題只有D選項纔是原子操作。

11、一般情況下,下面哪些操作會執行失敗?【多選】(BCD)

class A
{
public:
	string a;
	void f1()
	{
		printf("Hello World");
	}
	void f2()
	{
		a = "Hello World";
		printf("%s",a.c_str());
	}
	virtual void f3()
	{
		printf("Hello World");
	}
	virtual void f4()
	{
		a = "Hello World";
		printf("%s",a.c_str());
	}
};
A、A *aptr = NULL;  aptr->f1();
B、A *aptr = NULL;  aptr->f2();
C、A *aptr = NULL;  aptr->f3();
D、A *aptr = NULL;  aptr->f4();

至於A爲什麼正確,因爲A沒有使用任何成員變量,而成員函數是不屬於對象的,所以A正確。其實,A* aptr = NULL;aptr->f5();也是正確的,因爲靜態成員也是不屬於任何對象的。至於BCD,在B中使用了成員變量,而成員變量只能存在於對象,C有虛表指針,所以也只存在於對象中。D就更是一樣了。但是,如果在Class A中沒有寫public,那麼就全都是private,以至於所有的選項都將會失敗。

12、C++下,下面哪些template實例化使用,會引起編譯錯誤?【多選】(CEF)

template<class Type> class stack;
void fi(stack<char>);      //A
class Ex
{
	stack<double> &rs;    //B
	stack<int> si;        //C
};

int main(void)
{
	stack<char> *sc;      //D
	fi(*sc);              //E
	int i = sizeof(stack<string>);    //F
	
	return 0;
}
選C E F;  請注意stack和fi都只是聲明不是定義。我還以爲在此處申明後,會在其他地方定義呢,坑爹啊。
由於stack只是聲明,所以C是錯誤的,stack不能定義對象。E也是一樣,stack只是申明,所以不能執行拷貝構造函數,至於F,由於stack只是聲明,不知道stack的大小,所以錯誤。如果stack定義了,將全是正確的。
13、以下哪個說法正確()
int func()
{
	char b[2]={0};
	strcpy(b,"aaa");
}
A、Debug版崩潰,Release版正常
B、Debug版正常,Release版崩潰
C、Debug版崩潰,Release版崩潰
D、Debug版正常,Release版正常
選A。因爲在Debug中有ASSERT斷言保護,所以要崩潰,而在Release中就會刪掉ASSERT,所以會出現正常運行。但是不推薦如此做,因爲這樣會覆蓋不屬於自己的內存,這是搭上了程序崩潰的列車。

數據結構類

37、每份考卷都有一個8位二進制序列號,當且僅當一個序列號含有偶數個1時,它纔是有效的。例如:00000000 01010011 都是有效的序列號,而11111110不是,那麼有效的序列號共有(128)個。
38、對初始狀態爲遞增序列的數組按遞增順序排序,最省時間的是插入排序算法,最費時間的算法(B)
A、堆排序  B、快速排序   C、插入排序   D、歸併排序
39、下圖爲一個二叉樹,請選出以下不是遍歷二叉樹產生的順序序列的選項【多選】(BD)

A、ABCDEFIGJH
B、BDCAIJGHFE
C、BDCAIFJGHE
D、DCBJHGIFEA
40、在有序雙向鏈表中定位刪除一個元素的平均時間複雜度爲()
A、O(1)   B、O(N)   C、O(logN)      D、O(N*logN)

41、將10階對稱矩陣
壓縮存儲到一維數組A中,則數組A的長度最少爲()
A、100     B、40     C、55      D、80
42、將數組a[]作爲循環隊列SQ的存儲空間,f爲隊頭指示,r爲隊尾指示,則執行出隊操作的語句爲(B)
A、f = f+1     B、f = (f+1)%m      C、r = (r+1)%m     D、f = (f+1)%(m+1)
43、以下哪種操作最適合先進行排序處理?
A、找最大、最小值   B、計算算出平均值   C、找中間值  D、找出現次數最多的值
44、設有一個二維數組A[m][n],假設A[0][0]存放位置在644(10),A[2][2]存放位置在676(10),每個元元素佔一個空間,問A[3][3]存放在什麼位置?(C)腳註(10)表示用10進製表示
A、688     B、678     C、692     D、696
45、使用下列二維圖形變換矩陣A=T*a,將產生的變換結果爲(D)

A、圖形放大2倍
B、圖形放大2倍,同時沿X、Y座標軸方向各移動一個單位
C、沿X座標軸方向各移動2個單位
D、沿X座標軸放大2倍,同時沿X、Y座標軸方向各移動一個單位
46、體育課的鈴聲響了,同學們都陸續地奔向操場,按老師
的要求從高到矮站成一排。每個同學按順序來到操場時,都從排尾走向排頭,找到第一個比自己高的同學,並站到他的後面,這種站隊的方法類似於()算法。
A、快速排序      B、插入排序      C、冒泡排序    D、歸併排序
47、處理a.html文件時,以下哪行僞代碼可能導致內存越界或者拋出異常(B)
         int totalBlank = 0;
         int blankNum = 0;
         int taglen = page.taglst.size();
A       for(int i = 1; i < taglen-1; ++i)
        {
                 //check blank
B             while(page.taglst[i] == "<br>" && i < taglen)
               {
C                       ++totalBlank;
D                       ++i;
               }
E             if(totalBlank > 10)
F                      blankNum += totalBlank;
G             totalBlank = 0;
        }
注意:以下代碼中taglen是html文件中存在元素的個數,a.html中taglen的值是15,page.taglst[i]取的是a.html中的元素,例如page.taglst[1]的值是<html>
a.html的文件如下:
<html>
<title>test</title>

<body>
<div>aaaaaaa</div>
</body>
</html>
<br>
<br>
<br>
<br>
<br>
48、對一個有向圖而言,如果每個節點都存在到達其他任何節點的路徑,那麼就稱它是強連通的。例如,右圖就是一個強連通圖,事實上,在刪掉哪幾條邊後,它依然是強連通的。(A)

A、a       B、b        C、c             D、d

100、一種計算機,其有如下原子功能:
1、賦值   a=b
2、+1操作,++a; a+1;
3、循環,但是隻支持按次數的循環   for(變量名){/*循環裏面對變量的修改不影響循環次數*/}
4、只能處理0和正整數
5、函數調用    fun(參數列表)
請用僞代碼的形式分別在這個計算機上編程實現變量的加法、減法、乘法。

fun_add(a , b)
{
}
fun_multi(a , b)
{
}
fun_minus(a , b)
{
}
問題的關鍵在於如何實現自減一操作。
本來讓-1自增n次即可實現n的自減的,但系統偏偏又不支持負數。
fun_add(a , b)
{
	result = a;
	for(b)
		++result;
	return result;
}

fun_muti(a , b)
{
	result = 0;
	for(b)
		result = fun_add(result , a);
	return result;
}

dec(int n)
{
	temp = 0;
	result = 0;
	for(n)
	{
		result = temp;   //result永遠比temp少1,巧妙地減少了一次自增
		++temp;
	}
	return result;
}
/*
上面的dec這段函數代碼執行後,result的值將變爲n-1。注意到這段代碼在自增時是如何巧妙地延遲了一步的。
現在,我們相當於有了自減一的函數dec。實現a-b只需要令a自減b次即可
*/
fun_minus(a , b)
{
	result = a;
	for(b)
		result = dec(result);
}


101、實現一個隊鏈表排序的算法,C/C++可以使用std::list<int>,Java使用LinkedList<Integer>
要求先描述算法,然後再實現,算法效率儘可能高效。
主要考察鏈表的歸併排序。
要點:需要使用快、慢指針的方法,找到鏈表的的中間節點,然後進行二路歸併排序
typedef struct LNode
{
	int data;
	struct LNode *next;
}LNode , *LinkList;

// 對兩個有序的鏈表進行遞歸的歸併
LinkList MergeList_recursive(LinkList head1 , LinkList head2)
{
	LinkList result;
	if(head1 == NULL)
		return head2;
	if(head2 == NULL)
		return head1;
	if(head1->data < head2->data)
	{
		result = head1;
		result->next = MergeList_recursive(head1->next , head2);
	}
	else
	{
		result = head2;
		result->next = MergeList_recursive(head1 , head2->next);
	}
	return result;
}

// 對兩個有序的鏈表進行非遞歸的歸併
LinkList MergeList(LinkList head1 , LinkList head2)
{
	LinkList head , result = NULL;
	if(head1 == NULL)
		return head2;
	if(head2 == NULL)
		return head1;
	while(head1 && head2)
	{
		if(head1->data < head2->data)
		{
			if(result == NULL)
			{
				head = result = head1;
				head1 = head1->next;
			}
			else
			{
				result->next = head1;
				result = head1;
				head1 = head1->next;
			}
		}
		else
		{
			if(result == NULL)
			{
				head = result = head2;
				head2 = head2->next;
			}
			else
			{
				result->next = head2;
				result = head2;
				head2 = head2->next;
			}
		}
	}
	if(head1)
		result->next = head1;
	if(head2)
		result->next = head2;
	return head;
}

// 歸併排序,參數爲要排序的鏈表的頭結點,函數返回值爲排序後的鏈表的頭結點
LinkList MergeSort(LinkList head)
{
	if(head == NULL)
		return NULL;
	LinkList r_head , slow , fast;
	r_head = slow = fast = head;

	// 找鏈表中間節點的兩種方法
	/*
	while(fast->next != NULL)
	{
		if(fast->next->next != NULL)
		{
			slow = slow->next;
			fast = fast->next->next;
		}
		else
			fast = fast->next;
	}*/

	while(fast->next != NULL && fast->next->next != NULL)
	{
		slow = slow->next;
		fast = fast->next->next;
	}
	
	if(slow->next == NULL)    // 鏈表中只有一個節點
		return r_head;
	fast = slow->next;
	slow->next = NULL;
	slow = head;

	// 函數MergeList是對兩個有序鏈表進行歸併,返回值是歸併後的鏈表的頭結點
	//r_head = MergeList_recursive(MergeSort(slow) , MergeSort(fast));
	r_head = MergeList(MergeSort(slow) , MergeSort(fast));
	return r_head;
}

轉載請標明出處,原文地址:http://blog.csdn.net/hackbuteer1/article/details/8016173


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章