1.sizeof关键字
1.1 定义一个空的类型,里面没有任何成员变量和成员函数,对该类型求sizeof,得到的结果是多少?
答案:1
解析:
空类型的实例中不包含任何信息,本来求sizeof应该是0,但是当我们声明该类型的实例的时候,它必须在内存中占有一定的空间,否则无法使用这些实例。至于占用多少内存,由编译器决定。Visual Studio中每个空类型的实例占用1字节的空间。
1.2 如果在该类型中添加一个构造函数和析构函数,再对该类型求sizeof得到的结果又是多少?
答案:1
解析:
调用构造函数和析构函数只需要直到函数的地址即可,而这些函数的地址只与类型相关,而与类型的实例无关,编译器也不会因为这两个函数而在实例内添加任何额外的信息。
1.3 如果把析构函数标记为虚函数,sizeof得到的结果又是多少?
答案:(32位系统)4、(64位系统)8
解析:
C++的编译器一旦发现一个类型中有虚函数,就会为该类型生成虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针。在32位的机器上,一个指针占4字节的空间,如果在64位的机器上,一个指 针占8字节的空间。
2.数据结构
常用的数据结构:数组、字符串、链表、树、栈及队列
2.1 数组
数组占据一块连续的内存并按照顺序存储数据。创建数组时,首先指定数组的容量,然后根据大小分配内存。
数组中的内存是连续的,可根据下标读写任何元素,时间效率高,但经常有空闲的区域没有使用,空间效率不是很好。
2.2 找出数值中重复的数字
在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有哪几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者是3。
方法一:排序,将数组的数字排序,在排好序的数组中找到重复的数组,时间复杂度很大O(nlogn)。
方法二:把每一个数字都扫描,看与其他剩下的数字是否相同。时间复杂度是O(n^2),两次for循环找出相同的数。
方法三:哈希表,扫描数组里的每个数字,看哈希表里是否有这个数字,没有就将这个数字加进去,有的话,则该数字重复。时间复杂度是O(n),但提高时间效率是以一个大小为O(n)的哈希表为代价
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
方法四:数组里所有的数组都是0到n-1的范围内。如果数组里没有重复的数字,那么每个数字排序后的数字i都会在下标为i的位置上。由于数组中有重复的数字,那么这个位置上就会有多个数字,有些位置上也会没有数字。
从头到尾扫描这个数组的每个数字。当到下标为i的数字时,先比较这个数字m是否等于下标i,如果等于那么就扫描下一个数字;如果不是,那它和第m个数字相比较。如果和第m个数字一样,则找到重复的数字,因为该数字在第i个位置和第m个位置都出现了;如果不是则把该第i位置上的数字和第m个位置上的数字交换,刚在它原本属于的位置上去。重复此过程,找到重复的数字。(总体时间复杂度O(n))
测试用例:
(1)长度为n的数组里包含一个或多个重复的数字
(2)数组中不包含重复的数字
(3)无效的输入的测试用例:输入空指针、超出边界的数组值等
函数实现:
/*********************************
Function: ai_findDuplicteDigit
Description:找到整型数组中的重复的数字
Parameter: number 需要查找的数组, 数字是0-n-1
len 数据长度
pDupDigit 返回重复的数字
Output: None
Return: None
*************************************************/
int ai_findDuplicteDigit(int number[], int len, int *pDupDigit)
{
int i = 0;
int tmp = 0;
if (!number || len <= 0 || !pDupDigit)
{
return -1;
}
/* 校验值是否正确 */
for (i = 0; i < len; i++)
{
if (number[i] < 0 || number[i] >= len)
{
return -1;
}
}
for (i = 0; i < len; i++)
{
while (i != number[i])
{
if (number[i] != number[number[i]])
{
tmp = number[i];
number[i] = number[tmp];
number[tmp] = tmp;
}
else
{
*pDupDigit = number[i];
return 0;
}
}
}
return -1;
}
2.2 字符串
/*************************************************
Function: st_replaceBlank
Description:替换空格,实现将字符串中的每个空格替换成"%20"
在网络编程中,如果URL参数中含有特殊的字符,如空格、#等,则可能导致服务器端
无法获取正确的参数值,需要将这些特殊字符转换成服务器可识别的字符
转换规则:在’%'后面跟上ASCII码的两位十六进制表示。例如空格的ASCII是32,即十六进制0x20,
则空格替换为"%20"
解决方案有两种:空格是一个字符,但"%20"是三个字符
1.从前往后遇到空格将后面的字符往后移动,时间复杂度是O(n平方)
2. 时间空间为O(n)的方案
(1)遍历字符串,查找空格个数,替换字符串之后的总长度为原有字符串的总长度加上空格数乘以2
(2)从字符串的后面开始复制和替换,准备两个指针P1和P2,P1指向原始字符串的末尾,而P2指向替换之后的字符串的末尾
向前移动P1,逐个把它指向的字符复制到P2位置,遇到空格P1向前移动1格,P2移动3格
Parameter: string 字符串
length 字符串空间的总大小
Output: None
Return: None
*************************************************/
int st_replaceBlank(char string[], int length)
{
int blankNum = 0;
int realLength = 0;
int i = 0;
char *p1 = NULL;
char *p2 = NULL;
int outLength = 0;
if (!string || length <= 0)
{
return -1;
}
realLength = strlen(string);
if (realLength <= 0)
{
return 0;
}
/* 查询空字符个数 */
for (i = 0; i < realLength; i++)
{
if (string[i] == ' ')
{
blankNum++;
}
}
printf("blankNum:%d\n", blankNum);
if (blankNum == 0)
{
return 0;
}
outLength = realLength + 1 + 2 * blankNum;
if (length < outLength)
{
return -1;
}
p1 = &string[realLength + 1];
p2 = &string[outLength];
*p2 = *p1;
p1--;
p2--;
for (i = realLength; i >= 0; i--)
{
if (string[i] == ' ')
{
p1--;
*p2 = '0';
*(--p2) = '2';
*(--p2) = '%';
p2--;
}
else
{
*p2 = *p1;
p1--;
p2--;
}
}
return 0;
}