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;
}