文章大部分内容转载https://www.cnblogs.com/lanxuezaipiao/p/4127904.html
1.冒泡排序法:
如果有N个数字需要排序,那么需要进行(N-1)趟循环,第i趟循环需要对比的次数为(N-i)。所以可以用双重循环,外层循环用于控制循环的趟数,内层循环用于控制每一趟循环的次数。
冒泡排序的优点:每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值
冒泡排序法时间复杂度:
1).如果我们的数据正序,只需要走一趟即可完成排序。所需的比较次数C和记录移动次数M均达到最小值,即:Cmin=n-1;Mmin=0;所以,冒泡排序最好的时间复杂度为O(n)。
2).如果很不幸我们的数据是反序的,则需要进行n-1趟排序。每趟排序要进行n-i次比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:冒泡排序的最坏时间复杂度为:O(n2) 。
综上所述:冒泡排序总的平均时间复杂度为:O(n2) 。
双重for循环实现冒泡排序法:
2.有1,2,…,n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度O(1),使用交换,而且一次只能交换两个数。
这个题的特点是,数字是连续的如果是从1到n,那么最终排好序的数字和下标之间只差1,
,
3. 易误解:如果int a[5], 那么a与&a是等价的,因为两者地址相同。
一定要注意a与&a是不一样的,虽然两者地址相同,但意义不一样,&a是整个数组对象的首地址,而a是数组首地址,也就是a[0]的地址,a的类型是int[5],a[0]的类型是int,因此&a+1相当于a的地址值加上sizeof(int) * 5,也就是a[5],下一个对象的地址,已经越界了,而a+1相当于a的地址加上sizeof(int),即a[1]的地址。
4. 如何将一个小数分解成整数部分和小数部分?
采用库函数double modf(double x,double *integer)
#include<stdio.h>
#include<math.h>
int main(){
double x,fraction,integer;
while(~scanf("%lf",&x)){
fraction=modf(x,&integer);
printf("整数部分=%lf\n",integer);
printf("小数部分=%lf\n",fraction);
}
return 0;
}
5. 可作为函数重载判断依据的有:参数个数、参数类型、参数的排列顺序、const修饰符;
不可以作为重载判断依据的有:返回类型。
7. C的结构体和C++结构体的区别
(1)C的结构体内不允许有函数存在,C++允许有内部成员函数,且允许该函数是虚函数。所以C的结构体是没有构造函数、析 构函数、和this指针的。
(2)C的结构体对内部成员变量的访问权限只能是public,而C++允许public,protected,private三种。
(3)C语言的结构体是不可以继承的,C++的结构体是可以从其他的结构体或者类继承过来的。
8. 如何在类中定义常量成员并为其初始化?
解答:只能在初始化列表里对const成员初始化,像下面这样:
class CBook {
public:const double m_price;
类中的构造函数是为了初始化类中的成员变量的,一般的成员变量可以在构造函数内部进行初始化,但是对于常量成员
只可以在构造函数名后面,用初始化列表的形式进行初始化。CBook() :m_price(8.8) { }
};
9. 在定义类的成员函数时使用mutable关键字的作用是什么?
解答:当需要在const方法中修改对象的数据成员时,可以在数据成员前使用mutable关键字,防止出现编译出错。例子如下:
class CBook {
public:mutable double m_price; // 如果不加就会出错CBook(double price) :m_price(price) { }double getPrice() const; // 定义const方法
};
double CBook::getPrice() const {m_price = 9.8;return m_price;
}
10. 拷贝构造函数在哪些情况下被调用?
(1)函数的参数为类对象且参数采用值传递方式;
(2)将类对象做为函数的返回值。
11.在C++中,如果确定了某一个构造函数的创建过程,在该构造函数中如果调用了其它重载的构造函数,它将不会执行其它构造函数的初始化列表部分代码,而是执行函数体代码,此时已经退化成普通函数了。例子说明如下:
class CBook {
public:double m_price;
这是一个构造函数CBook() {
///在这个无参的构造函数中调用了另外一个重载的构造函数,那么这个构造函数的初始化列表将不会执行。而是直接执行函数体。CBook(8.8);}
这个是一个重载的构造函数CBook(double price) : m_price(price) { }
};
int main() {CBook c;cout << c.m_price << endl; // 此时并不会输出理想中的8.8
}
12. 静态数据成员只能在全局区域进行初始化,而不能在类体中进行(构造函数中初始化也不行),且静态数据成员不涉及对象,因此不受类访问限定符的限制。
class CBook {
public:static double m_price;
};
double CBook::m_price = 8.8;//只能在这里(全局区)进行初始化,不能在构造函数中进行初始化。
13. 重载++和–时是怎么区分前缀++和后缀++的?
例如当编译器看到++a(先自增)时,它就调用operator++(a);
但当编译器看到a++时,它就调用operator++(a, int)。即编译器通过调用不同的函数区别这两种形式这里的int 是一个占位符。
14. C++的多态性分为静态多态和动态多态。
静态多态性:编译期间确定具体执行哪一项操作,主要是通过函数重载和运算符重载来实现的;可以通过(参数数量,参数类型,参数的顺序来重载)
动态多态性:运行时确定具体执行哪一项操作,主要是通过虚函数来实现的。
多态发生的条件:有继承,有虚函数的重写,有父类指针指向子类对象。
15. 虚函数原理考察
class A {
public:virtual void funa(); ///指针指向虚函数表virtual void funb();void func(); ///代码区static void fund();全局区static int si; 全局区
private:int i; 栈区char c; 栈区
};
关于类占用的内存空间,有以下几点需要注意:
(1)如果类中含有虚函数,则编译器需要为类构建虚函数表,类中需要存储一个指针指向这个虚函数表的首地址,注意不管有几个虚函数,都只建立一张表,所有的虚函数地址都存在这张表里,类中只需要一个指针指向虚函数表首地址即可。
(2)类中的静态成员是被类所有实例所共享的,它不计入sizeof计算的空间
(3)类中的普通函数或静态普通函数都存储在栈中,不计入sizeof计算的空间
(4)类成员采用字节对齐的方式分配空间
(5)类中的方法放在代码区
(6)static或者字符串常量放在数据区或者是常量区
(7)类中的普通成员变量放在栈中
(8)通过new分配的变量存储在堆区
C语言中的四区模型,栈区,堆区,代码区,常量区或者全局区
答案:12(32位系统)或16(64位系统)
16. 虚继承的作用是什么?
在多继承中,子类可能同时拥有多个父类,如果这些父类还有相同的父类(祖先类),那么在子类中就会有多份祖先类。例如,类B和类C都继承与类A,如果类D派生于B和C,那么类D中就会有两份A。为了防止在多继承中子类存在重复的父类情况,可以在父类继承时使用虚函数,即在类B和类C继承类A时使用virtual关键字。
17. 32位系统和64位系统各个数据类型所占的内存空间
类和结构体中一样,有四字节补齐效果,如果计算的总共的字节数,除上4之后的余数不为0,那么最终的所占字节数为上面所做除法的商再加上4个字节。例如,计算的总字节数为15,那么最终的字节数是12+4=16个字节。
const关键字:
1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化。因为以后就没有机会再改变它了。
2)对指针来说,可以指定指针的本身为const,也可以指定指针所指向的数为const。或二者同时为const。
3)在一个函数的声明中,const可以修饰形参,表明它是一个输入参数。在函数内不能改变其值。
4)对于类的成员函数,若指定其为const类型。则表明其是一个常量函数。不能修改类的成员变量。
5)对于类的成员函数,有时候必须指定其返回值为const类型。以使得其返回值不为“左值”。
static关键字:
1)函数体内static变量的作用范围为函数体。不同于auto变量。该变量的内存只被分配一次。因此其值在下次调用时仍维持上次的值。
2)在模块内的static全局变量可以被模块内的所有函数访问。但不能被模块外的其他函数访问。
3)在模块内的static函数只可被这一模块内的其它函数调用。这个函数的使用范围被限制在声明它的模块内。
4)在类中的static成员变量属于整个类所有,对类的所有对象只有一份复制。
5)在类中的static成员函数属于整个类所有,这个函数不接受this指针,因而只能访问类的static成员变量。