1.下列程序共调用x(int n)有 18次。
#include<iostream>
using namespacestd;
int cnt=0;
int x(int n) {
cnt++;
if(n<=3)
{
return 1;
}
else
{
return x(n-2)+x(n-4)+1;}
}
int main() {
x(x(8));
cout<<cnt;
return 0;
}
2.
#include<iostream>
using namespacestd;
int main() {
int a[]={2,4,6,8,10},*p,**k;
p=a;
cout<<p<<""<<*p<<endl;
k=&p;
cout<<*(p++)<<endl;
cout<<k<<""<<*k<<" "<<**k<<endl;
return 0;
}
3.
#include<iostream>
#include<string.h>
using namespacestd;
int main() {
int a[][3]={{1},{3,2},{4,5,6},{0}};
cout<<sizeof(a);
return 0;
}
4.两个等价线程并发执行下列程序,a为全局变量,初始为0,假设printf、++、--操作都是原子性的,则输出肯定不是哪个?
void foo() {
if(a<=0) {
a++;
}
else {
a--;
}
printf("%d",a);
}
与a有关的语句有3个:a<=0,判断语句,从内存取值,不写回内存;a++/a--,从内存取值,有对a的赋值,结果要写回内存;printf打印a,要从内存取值。
1)、线程P1执行完foo(),线程P2再执行foo()。结果是10。
2)、线程P1从内存取出a=0,执行判断语句后等待;线程P2从内存取出a=0,执行判断语句后等待;线程P1再执行a++,a变为1,写回内存,等待;线程P2从内存取出a=1,再执行a++,a变为2,写回内存,等待;线程P1执行printf,输出2,线程P2执行printf,输出2。结果是22。
3)、线程P1从内存取出a=0,执行判断语句后等待;线程P2从内存取出a=0,执行判断语句后等待;线程P1再执行a++,a变为1,写回内存,继续执行printf,输出1,等待;线程P2从内存取出a=1,再执行a++,a变为2,写回内存,继续执行printf,输出2。结果是12。
4)、还有种可能是00。但不会是01。
分析二:
原子操作指的是这个过程或者直白点说,这句函数不会被中断。因此printf、++、--这三个操作之间排列两个线程就行。
A、如果要第一个值输出0,线程1进入判断并实现++,线程2此时进入判断实现--,a=0,两个线程下一句都是print,结果将是00;(考虑到线程并发和内存抢占的情况,暂不考虑一个线程print0以后还是这个线程执行一遍程序打印出1,而是由另一个线程来print0)
B、线程1判断,执行++,打印1,线程2判断,执行--,打印0,结果10;
C、线程1进入判断,线程2进入判断,线程1执行++,打印1,线程2执行++,打印2,结果12;
D、线程1进入判断,线程2进入判断,线程1执行++,线程2执行++,各自打印出2,结果22。
5. 求最大公约数的最常用的算法是欧几里得算法,也称为辗转相除法.点击打开链接
问题定义为求i和j的最大公约数gcd(i,j),其中i和j是整数,不妨设i>j.
算法可以递归的表示:
1.如果j能整除i,那么gcd(i,j)=j;
2.j不能整除i,令r=i%j,那么gcd(i,j)=gcd(j,r).
使用C语言实现:
int gcd(int i, intj) { int r = i % j; return r == 0 ? j : gcd(j, r);}正确性分析:
算法的步骤1,显然成立(最大公约数定义).关键是要证明步骤2.
设d是i和j的最大公约数,
那么i=md,j=nd,m和n互质(否则d不是最大公约数).
由r=i%j可以得到i=kj+r,k=⌊m/n⌋,k≥1(我们前面假设过i>j).
把i=md,j=nd代入得到
md=knd+r
那么
r=(m-kn)d
m-kn和m也是互质的.
所以得到d是j和r的最大公约数.
时间复杂度分析:
逆着看该算法,最后的余数是0,倒数第二次余数是d,倒数第三次是kd,k>1…
由于组成了一个数列,{0,d,kd,nkd+d,…}
数列的n项加上n+1项,比n+2项要小,所以比斐波纳契数列增长的要快.
我们已知斐波纳契数列增长速度是指数,那么待分析的数列也是指数增长.
设欧几里得算法需要k次,那么j=O(2^k),则k=O(lg j).
所以欧几里得算法求最大公约数的时间复杂度是对数量级的,速度非常快.
7. 以下代码会调用多少次拷贝构造函数?
Widget f(Widget u){
Widget v(u);
Widget w=v;
return w;
}
main() {
Widget x;
Widget y=f(f(x));
}
分析:y=f(f(x)) 有两层 f() ,为了说明过程,把里面的一层标明为 f_1 ,外面一层标明为 f_2 。则 7 次调用分别是:
x -> f_1 的 u
f_1 的 u->f_1 的 v
f_1 的 v-> f_1 的 w
f_1 的 w->f_2 的 u
f_2 的 u->f_2 的 v
f_2 的 v->f_2 的 w
f_2 的 w->y
分析二:
1),可能有朋友对Widget w=v;有疑惑。
这里的 =号,是v去初始化w。对象的初始化当然是去调用构造函数了,而不是重载的=运算符。
如果,
Widget w;
w=v;
那么此时=号调用的是Widget operator=(constWidget&)赋值函数 因为 Widget w;已经把w初始化过了。
2),单个的 f(x) 执行时,会调用4次copy constructer.
本题中,f(x)的返回值直接又作了f()的参数。f(f(x))的返回值又去初始化y,共7次