1.1一维数组的声明与字符数组
1.1.1一维数组的声明与初始化
1.一维数组的声明
例1:如下定义是否正确?
int& a[10];
error C2109: 下标要求数组或指针类型
例2:定义数组a的引用。
int a[6] = { 0,2,4,6,8,10 }; int(*p)[6] = a;
2.一维数组的初始化
例1:给定如下代码:
数组x和y的值为?
int x[4] = { 0 }; int y[4] = { 1 };
x{0,0,0,0}
y{1,0,0,0}
1.1.2C风格字符串与字符数组
1.C风格字符串
例2:下列哪些是C风格字符串?
char ca1[] = { 'C','+','+' }; char ca2[] = { 'C','+','+' ,'\0' };//是 char ca3[] = "C++";//是 const char *cp = "C++";//是 char *cp1 = ca1; char *cp2 = ca2;//是
2.字符数组
例1:下面的初始化是否正确?
const char ch3[6] = "Deniel";
error C2117: “ch3”: 数组界限溢出
例2:给出以下定义,则正确的叙述为数组x的长度大于数组y的长度。
char x[] = "abcdefg"; char y[] = { 'a','b','c','d','e','f','g' }; printf("%d\n", sizeof(x)); printf("%d\n", sizeof(y));
例3:下面程序段的运行结果是ab。
char c[5] = { 'a','b','\0','c','\0' }; printf("%s\n", c);
1.2二维数组
1.2.1二维数组的声明与初始化
例1:以下声明是否正确?
int disp(int a[][]);
error C2087: “a”: 缺少下标
例2:下列代码输出是1。
int a[3][2] = { (0,1),(2,3),(4,5) }; int *p = a[0]; printf("%d\n", p[0]);
1.2.2行优先存储与列优先存储
例1:有一矩阵大小为16Kx16K,若对两个这样的矩阵做加法运算,行优先读取与列优先读取的区别为行优先快。
例2:下列程序执行后的输出结构是6。
#include <stdio.h> #include <windows.h> int main() { int a[3][3], *p, i; p = &a[0][0]; for (i = 0; i < 9; i++) { p[i] = i + 1; } printf("%d\n", a[1][2]); system("pause"); return 0; }
例3:下面的函数是一个用指针实现二维数组的读取函数,请完成该函数。
#include <stdio.h> #include <windows.h> #define M 3 #define N 4 int get(int *p, int i, int j) { if (NULL == p || i < 0 || i >= M || j < 0 || j >= N) { return (0); } return *(p + i*N + j); } int main() { int a[M][N] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} }; printf("a[2][3] == %d\n", get(&a[0][0], 2, 3)); system("pause"); return 0; }
例4:有一个二维数组a[1...100,1...65]有100行,65列,我们以行序为主序,如果该数组的基地址是10000,且每个元素占2个存储单元,请问a[56,22]的存储地址是?
10000+[(56-1)x65+(22-1)]x2
例5:下面程序执行的结果是:h。
#include <stdio.h> #include <windows.h> int main() { char matrix[3][3] = { {'a','b','c'},{ 'd','e','f' },{ 'g','h','i' } }; printf("%c\n", matrix[1][4]); system("pause"); return 0; }
1.3数组指针、指针数组与数组名的指针操作
1.3.1指针运算——算术运算、关系运算
例1:What is output if you compile and execute the following code?
Garbage value
指向常量的指针
#include <stdio.h> #include <windows.h> int main() { int i = 11; int const *p = &i; p++; printf("%d\n", *p); system("pause"); return 0; }
1.3.2指针数组与数组指针
例1:设有“int w[3][4];”,pw是与数组名w等价的数组指针,则pw的初始化语句为int(*pw)[4] = w;。
1.3.3指针运算在数组中的应用
例1:下述代码是否正确?
char a[] = "hello"; a[0] = 'x'; char* q = a; q[0] = 'b'; char* p = "hello";/*并不是把整个字符串装入指针变量,而是把存放该字符串的首地址装入指针变量*/ p[0] = 'x';
例2:针对int a[10];以下表达式不可以表示a[1]的地址是?
printf("0X%x\n", a + sizeof(int)); printf("0X%x\n", &a[0] + 1); printf("0X%x\n", (int*)&a + 1); printf("0X%x\n", (int*)((char*)&a + sizeof(int)));
0X699efcd8
0X699efccc
0X699efccc
0X699efccc
请按任意键继续. . .
例3:以下程序的运行结构是ga。
#include <stdio.h> #include <windows.h> int main() { char a[] = { "programming" }, b[] = { "language" }; char *p1, *p2; int i; p1 = a, p2 = b; for (i = 0; i < 7; i++) { if (*(p1 + i) == *(p2 + i)) { printf("%c", *(p1 + i)); } } system("pause"); return 0; }
例4:下面程序执行的结果是编译错误。
error C2106: “+=”: 左操作数必须为左值
#include <stdio.h> #include <windows.h> int main() { char s[] = "abcde"; s += 2; printf("%c\n", s[0]); system("pause"); return 0; }
例5:以下程序执行后的输出结果是4。
#include <stdio.h> #include <windows.h> void sum(int *a) { a[0] = a[1]; } int main() { int aa[10] = { 1,2,3,4,5,6,7,8,9,10 }, i; for (i = 2; i >= 0; i--) { sum(&aa[i]); } printf("%d\n", aa[0]); system("pause"); return 0; }
指针运算在高维数组中的应用
例1:下列关于数组的初始化正确的是?
#include <stdio.h> #include <windows.h> int main() { char str1[2] = { "a","b" };//error C2078: 初始值设定项太多 char str2[2][3] = { "a","b" }; char str3[2][3] = { {'a','b'},{ 'e','f' },{ 'g','h' } };//error C2078: 初始值设定项太多 char str4[] = { "a","b" };//error C2078: 初始值设定项太多 system("pause"); return 0; }
例2:数组int a[3][4];则下列能表示a[1][2]元素值的是。
printf("%d\n", *(*(a + 1) + 2)); printf("%d\n", *(a + 1 + 2)); printf("%d\n", (&a[0] + 1)[2]); printf("%d\n", *(a[0] + 1));
7
-1334248120
-1334248120
2
请按任意键继续. . .
例3:写出如下程序片段的输出结果5。
int a[] = { 1,2,3,4,5 }; int *ptr = (int *)(&a + 1); printf("%d\n", *(ptr - 1));
例4:求下述代码的输出结果7_12。
int a[2][2][3] = { {{1,2,3},{4,5,6}},{ { 7,8,9 },{ 10,11,12} } }; int *ptr = (int *)(&a + 1); printf("%d_%d\n", *(int *)(a + 1), *(ptr - 1));
例5:有以下程序,程序运行后的输出结果是Beijing。
#include <stdio.h> #include <windows.h> int main() { char str[][10] = { "China","Beijing" }, *p = str[0]; printf("%s\n", p + 10); system("pause"); return 0; }
1.4数组的应用
1.4.1线性表的顺序存储
例1:在n个结点的顺序表中,算法的时间复杂度是O(1)的操作是访问第i个结点(1<=i<=n)和求第i个结点的直接前驱(2<=i<=n)。
1.4.2对称矩阵的压缩
例1:将10阶对称矩阵压缩存储到一维数组A中,则数组A的长度最少为。
10阶对称矩阵共有10x10个元素,压缩到一维数组存储时,需要存储对角线以上或以下的元素共45个,加上对角线上的元素,共55个。
本章习题
1.下面选项中错误的是?
B.
int N=10;
int x[N];
C.
int x[0..10];
D.
int x[];
2.下述代码的输出结果是什么?
bcd
请按任意键继续. . .
#include <iostream> int main() { char a[] = "abcd"; char *p = a; int b = strlen(a); *a = p[b]; ++p; std::cout << p << std::endl; std::cout << a << std::endl; system("pause"); return 0; }
3.设数组定义为a[60][70],每个元素占2个存储单元,数组按照列优先存储,元素a[0][0]的地址为1024,那么元素a[32][58]的地址为?
1024+(58x60+32)x2=2048
4.设有一个二维数组A[m][n],假设A[0][0]存放位置在644(10),A[2][2]存放位置在676(10),每个元素占一个空间,问A[3][3]存放在什么位置?脚注表示用十进制表示。
A[2][2]的地址676=644+(2xn+2),求得n=15
A[3][3]的地址为644+(3xn+3)=692
5.请用文字说明p是何种类型变量。
int (*p)[n];
p是数组指针,指向一个长度为n的int型数组,p的类型为int (*)[n]。
6.若有以下说明和语句:
int c[4][5], (*p)[5]; p = c; printf("%d\n", *(*(p + 2) + 3));
7.将以下程序补充完整。
char a[2][2][3] = { {{1,6,3},{5,4,15}},{ { 3,5,33 },{ 23,12,7 }} };; for (int i = 0; i < 12; i++) { printf("%d\n", a[i / 6][i / 3 % 2][i % 3]); }
8.有以下定义和语句:
int a[3][2] = { 1,2,3,4,5,6 }, *p[3]; p[0] = a[1]; printf("%d\n", *(p[0] + 1));//4
9.若定义int a[2][3]={},以下描述正确的有?
458357204
8
8
458357192
请按任意键继续. . .
printf("%d\n", *(a + 1)); printf("%d\n", *(a[1] + 1)); printf("%d\n", **(a + 1) + 2); printf("%d\n", a[0]);
10.int A[2][3] = { 1,2,3,4,5,6 };,则A[1][0]和*(*(A + 1) + 1)的值分别是4 5?
11.以下程序打印的两个字符分别是c g。
#include <stdio.h> #include <windows.h> struct object { char data[3]; }; int main() { object obj_array[3] = { {'a','b','c'},{ 'd','e','f' },{ 'g','h','i' } }; object *cur = obj_array; printf("%c %c\n", *(char *)((char *)(cur)+2), *(char *)(cur + 2)); printf("%c %c\n", *((char *)(cur)+2), *(char *)(cur + 2)); system("pause"); return 0; }
12.下面程序执行结果为。
4 1101 13002 60
请按任意键继续. . .
#include <stdio.h> #include <windows.h> int main() { 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)); system("pause"); return 0; }
13.对于数组元素a[3][4],下列哪个不能表示a[1][1]?
6
6
590149912
5
请按任意键继续. . .
#include <stdio.h> #include <windows.h> int main() { int a[3][4] = { {1,2,3,4}, { 5,6,7,8}, { 9,10,11,12} }; printf("%d\n", *(&a[0][0] + 5)); printf("%d\n", *(*(a + 1) + 1)); printf("%d\n", *(&a[1] + 1)); printf("%d\n", *(&a[0][0] + 4)); system("pause"); return 0; }
14.将一个二维N*N矩阵顺时针旋转90°,例如a[2][2] = { 1,2,3,4 },旋转过后a[2][2] = { 4,1,3,2 }。
#include <stdio.h> #include <windows.h> #define N 4 void rotate(int matrix[][N]) { for (int layer = 0; layer < N / 2; ++layer) { int first = layer; int last = N - 1 - layer; for (int i = first; i < last; ++i) { int offset = i - first; int top = matrix[first][i];//save top matrix[first][i] = matrix[last - offset][first];//left->top matrix[last - offset][first] = matrix[last][last - offset];//bottom->left matrix[last][last - offset] = matrix[i][last];//right->bottom matrix[i][last] = top;//top->right } } } int main() { int a[N][N] = { {1,2,3,4}, { 5,6,7,8 }, { 9,10,11,12}, { 13,14,15,16 } }; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf("%d ", a[i][j]); } printf("\n"); } printf("\n"); rotate(a); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf("%d ", a[i][j]); } printf("\n"); } system("pause"); return 0; }
15.数组乘积
输入:一个长度为n的整数数组input;
输出:一个长度为n的整数数组result,满足result[i]=input数组中除了input[i]之外所有数的乘积(假设不会溢出)。比如输入:input={2,3,4,5},输出result={60,40,30,24}。
程序要求:具有线性复杂度,且不能使用除法运算符。
int *cal(int *input, int n) { int i; int *result = new int[n]; result[0] = 1; for (i = 1; i < n; ++i) { result[i] = result[i - 1] * input[i - 1]; } result[0] = input[n - 1]; for (i = n - 2; i > 0; --i) { result[i] *= result[0]; result[0] *= input[i]; } return result;//注意result需要由此函数调用方调用“delete[]”来释放内存 }
16.在有n个整数的序列中找出最大值和最小值,最少需要的比较次数是?
3n/2
17.从n个数里面找最大的两个数理论最少需要比较?
n+logn-2
18.一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。
int arr[100], rightMin[100]; void smallLarge(int *arr, int *rightMin, int n) { int i, leftMax; rightMin[n - 1] = arr[n - 1]; for (i = n - 2; i >= 0; --i) { if (arr[i] < arr[i + 1]) { rightMin[i] = arr[i]; } else { rightMin[i] = rightMin[i + 1]; } } leftMax = 0x80000000; for (i = 0; i < n; ++i) { if (arr[i] >= leftMax) { leftMax = arr[i]; if (leftMax == rightMin[i]) { printf("%d\n", leftMax); } } } }
19.数组中有一个数字出现的次数超过了数组长度的一半,请找出这个数字。
#include <stdio.h> #include <windows.h> int funtion(int data[], int length) { int currentAxis; int currentNum = 0; for (int i = 0; i < length; i++) { if (currentNum == 0) { currentAxis = data[i]; currentNum = 1; } else { if (currentAxis == data[i]) { currentNum++; } else { currentNum--; } } } return currentAxis; } int main() { int data[] = { 0,1,2,1,1 }; int axis = funtion(data, 5); printf("%d\n", axis); system("pause"); return 0; }