ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# C数组 C 语言支持**数组**数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 numbers\[0\]、numbers\[1\]、...、numbers\[99\] 来代表一个个单独的变量。数组中的特定元素可以通过索引访问。 所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。 ![](https://box.kancloud.cn/2015-12-13_566d2e1e9fb32.jpg) ## 声明数组 在 C 中要声明一个数组,需要指定元素的类型和元素的数量,如下所示: ~~~ type arrayName [ arraySize ]; ~~~ 这叫做一维数组。**arraySize**必须是一个大于零的整数常量,**type**可以是任意有效的 C 数据类型。例如,要声明一个类型为 double 的包含 10 个元素的数组**balance**,声明语句如下: ~~~ double balance[10]; ~~~ 现在*balance*是一个可用的数组,可以容纳 10 个类型为 double 的数字。 ## 初始化数组 在 C 中,您可以逐个初始化数组,也可以使用一个初始化语句,如下所示: ~~~ double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0}; ~~~ 大括号 { } 之间的值的数目不能大于我们在数组声明时在方括号 \[ \] 中指定的元素数目。 如果您省略掉了数组的大小,数组的大小则为初始化时元素的个数。因此,如果: ~~~ double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0}; ~~~ 您将创建一个数组,它与前一个实例中所创建的数组是完全相同的。下面是一个为数组中某个元素赋值的实例: ~~~ balance[4] = 50.0; ~~~ 上述的语句把数组中第五个元素的值赋为 50.0。所有的数组都是以 0 作为它们第一个元素的索引,也被称为基索引,数组的最后一个索引是数组的总大小减去 1。以下是上面所讨论的数组的的图形表示: ![](https://box.kancloud.cn/2015-12-14_566e449008415.jpg) ## 访问数组元素 数组元素可以通过数组名称加索引进行访问。元素的索引是放在方括号内,跟在数组名称的后边。例如: ~~~ double salary = balance[9]; ~~~ 上面的语句将把数组中第 10 个元素的值赋给 salary 变量。下面的实例使用了上述的三个概念,即,声明数组、数组赋值、访问数组: ## 实例 ``` #include <stdio.h> int main () { int n[ 10 ]; /* n 是一个包含 10 个整数的数组 */ int i,j; /* 初始化数组元素 */ for ( i = 0; i < 10; i++ ) { n[ i ] = i + 100; /* 设置元素 i 为 i + 100 */ } /* 输出数组中每个元素的值 */ for (j = 0; j < 10; j++ ) { printf("Element[%d] = %d\n", j, n[j] ); } return 0; } ``` 当上面的代码被编译和执行时,它会产生下列结果: ~~~ Element[0] = 100 Element[1] = 101 Element[2] = 102 Element[3] = 103 Element[4] = 104 Element[5] = 105 Element[6] = 106 Element[7] = 107 Element[8] = 108 Element[9] = 109 ~~~ 数组练习: 1 将数组A中的内容和数组B中的内容进行交换。(数组长度相同) 2 计算一个数组中数字的最大值最小值及其所在的位置 3 有一个有序的数组,用户输入一个数字k,将k插入数组。要求插入后数组依然有序 4 用数组保存 Fibonacci 数列的前20项,以5个数为一行的形式输出 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597 5 数组中存储学生成绩,计算该班级最高分,最低分,平均分,及格人数(60分以上) 成绩用户输入 当用户输入-1 表示输入结束 6 用户输入5个数,将其反序输出 7 用户输入5个数,将其翻转后输出 8 用户输入一串字符,统计单词的数量 # 冒泡排序法 在实际开发中,有很多场景需要我们将数组元素按照从大到小(或者从小到大)的顺序排列,这样在查阅数据时会更加直观,例如: * 一个保存了班级学号的数组,排序后更容易分区好学生和坏学生; * 一个保存了商品单价的数组,排序后更容易看出它们的性价比。 对数组元素进行排序的方法有很多种,比如冒泡排序、归并排序、选择排序、插入排序、快速排序等,其中最经典最需要掌握的是「冒泡排序」。 以从小到大排序为例,冒泡排序的整体思想是这样的: * 从数组头部开始,不断比较相邻的两个元素的大小,让较大的元素逐渐往后移动(交换两个元素的值),直到数组的末尾。经过第一轮的比较,就可以找到最大的元素,并将它移动到最后一个位置。 * 第一轮结束后,继续第二轮。仍然从数组头部开始比较,让较大的元素逐渐往后移动,直到数组的倒数第二个元素为止。经过第二轮的比较,就可以找到次大的元素,并将它放到倒数第二个位置。 * 以此类推,进行 n-1(n 为数组长度)轮“冒泡”后,就可以将所有的元素都排列好。 整个排序过程就好像气泡不断从水里冒出来,最大的先出来,次大的第二出来,最小的最后出来,所以将这种排序方式称为 下面我们以“3  2  4  1”为例对冒泡排序进行说明。 第一轮  排序过程 3  2  4  1    (最初) 2  3  4  1    (比较3和2,交换) 2  3  4  1    (比较3和4,不交换) 2  3  1  4    (比较4和1,交换) 第一轮结束,最大的数字 4 已经在最后面,因此第二轮排序只需要对前面三个数进行比较。 第二轮  排序过程 2  3  1  4 (第一轮排序结果) 2  3  1  4 (比较2和3,不交换) 2  1  3  4 (比较3和1,交换) 第二轮结束,次大的数字 3 已经排在倒数第二个位置,所以第三轮只需要比较前两个元素。 第三轮  排序过程 2  1  3  4  (第二轮排序结果) 1  2  3  4  (比较2和1,交换) 至此,排序结束。 ## 算法总结及实现 对拥有 n 个元素的数组 R\[n\] 进行 n-1 轮比较。 第一轮,逐个比较 (R\[1\], R\[2\]),  (R\[2\], R\[3\]),  (R\[3\], R\[4\]),  …….  (R\[N-1\], R\[N\]),最大的元素被移动到 R\[n\] 上。 第二轮,逐个比较 (R\[1\], R\[2\]),  (R\[2\], R\[3\]),  (R\[3\], R\[4\]),  …….  (R\[N-2\], R\[N-1\]),次大的元素被移动到 R\[n-1\] 上。 。。。。。。 以此类推,直到整个数组从小到大排序。 具体的代码实现如下所示: ``` ~~~ #include <stdio.h> int main(){ int nums[10] = {4, 5, 2, 10, 7, 1, 8, 3, 6, 9}; int i, j, temp; //冒泡排序算法:进行 n-1 轮比较 for(i=0; i<10-1; i++){ //每一轮比较前 n-1-i 个,也就是说,已经排序好的最后 i 个不用比较 for(j=0; j<10-1-i; j++){ if(nums[j] > nums[j+1]){ temp = nums[j]; nums[j] = nums[j+1]; nums[j+1] = temp; } } } //输出排序后的数组 for(i=0; i<10; i++){ printf("%d ", nums[i]); } printf("\n"); return 0; } ~~~ 运行结果: 1 2 3 4 5 6 7 8 9 10 ```