数组深度剖析

 

这里注意,上面我们说当[]里的不是整数的时候,编译器自动取整,可惜我们这里使用的gcc不支持这个,在Windows下的TC是对此支持的。

一维数组的初始化
给数组赋值除了用赋值语句一个一个赋值以外,还可以采用初始化赋值和动态赋值,数组的初始化是说在数组定义的时候赋值,数组的初始化是在程序编译阶段进行的,这样减少运行时间、提高效率。
初始化的一般形式:类型说明符 数组名[常量表达式] = {值,值,….值};
例如:
A[3] = {0,1,2};
注意:
1、 可以只给数组中的部分元素赋值,没有的自动为0
2、 只能逐个赋值,不可给整个数组赋值
3、 如给全部元素赋值,那么[]里的常量表达式可是缺省。

二维数组
二维数组的定义

前面介绍的数组只有一个下标,称为一维数组, 其数组元素也称为单下标变量。在实际问题中有很多量是二维的或多维的, 因此C语言允许构造多维数组。多维数组元素有多个下标, 以标识它在数组中的位置,所以也称为多下标变量。 本小节只介绍二维数组,多维数组可由二维数组类推而得到。二维数组类型说明二维数组类型说明的一般形式是:
  类型说明符 数组名[常量表达式1][常量表达式2]…;
  其中常量表达式1表示第一维下标的长度,常量表达式2 表示第二维下标的长度。例如:
  int a[3][4]; 说明了一个三行四列的数组,数组名为a,其下标变量的类型为整型。该数组的下标变量共有3×4个,即:
  a[0][0],a[0][1],a[0][2],a[0][3]
  a[1][0],a[1][1],a[1][2],a[1][3]
  a[2][0],a[2][1],a[2][2],a[2][3]
二维数组在概念上是二维的,即是说其下标在两个方向上变化, 下标变量在数组中的位置也处于一个平面之中, 而不是象一维数组只是一个向量。但是,实际的硬件存储器却是连续编址的, 也就是说存储器单元是按一维线性排列的。 如何在一维存储器中存放二维数组,可有两种方式:一种是按行排列, 即放完一行之后顺次放入第二行。另一种是按列排列, 即放完一列之后再顺次放入第二列。C语言中是按行排列的。
二维数组的表示方法
 二维数组的元素也称为双下标变量,其表示的形式为: 数组名[下标][下标]
  其中下标应为整型常量或整型表达式。例如: a[3][4] 表示a数组三行四列的元素。
  下标变量和数组说明在形式中有些相似,但这两者具有完全不同的含义。 数组说明的方括号中给出的是某一维的长度,即可取下标的最大值; 而数组元素中的下标是该元素在数组中的位置标识。前者只能是常量, 后者可以是常量,变量或表达式。
  一个学习小组有5个人,每个人有三门课的考试成绩。求全组分科的平均成绩和各科总平均成绩。
  课程 成绩姓名 Math C DBASE
  张 80 75 92
  王 61 65 71
  李 59 63 70
  赵 85 87 90
  周 76 77 85
  可设一个二维数组a[5][3]存放五个人三门课的成绩。再设一个一维数组v[3]存放所求得各分科平均成绩,设变量l为全组各科总平均成绩。编程如下:
  void main()
  {
  int i,j,s=0,l,v[3],a[5][3];
  printf("input score\n");
  for(i=0;i<3;i++){
  for(j=0;j<5;j++)
  { scanf("%d",&a[j]);
  s=s+a[j];}
  v=s/5;
  s=0;
  }
  l=(v[0]+v[1]+v[2])/3;
  printf("math:%d\nc languag:%d\ndbase:%d\n",v[0],v[1],v[2]);
  printf("total:%d\n",l);
  } for(i=0;j<3;i++)
  for(j=0;j<5;j++)
  { scanf("%d",&a[j]);
  s=s+a[j];}
  v=s/5;
  s=0;
  }
  l=(v[0]+v[1]+v[2])/3;
程序中首先用了一个双重循环。 在内循环中依次读入某一门课程的各个学生的成绩,并把这些成绩累加起来, 退出内循环后再把该累加成绩除以5送入v之中,这就是该门课程的平均成绩。外循环共循环三次,分别求出三门课各自的平均成绩并存放在v数组之中。退出外循环之后,把v[0],v[1],v[2]相加除以3即得到各科总平均成绩。最后按题意输出各个成绩。
 二维数组的初始化
二维数组初始化也是在类型说明时给各下标变量赋以初值。 二维数组可按行分段赋值,也可按行连续赋值。 例如对数组a[5][3]:
  1.按行分段赋值可写为static int a[5][3]={ {80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85} };
  2.按行连续赋值可写为static int a[5][3]={ 80,75,92,61,65,71,59,63,70,85,87,90,76,77,85 };
  这两种赋初值的结果是完全相同的。
  void main()
  {
  int i,j,s=0,l,v[3];
  static int a[5][3]={ {80,75,92},{61,65,71},{59,63,70},
  {85,87,90},{76,77,85} };
  for(i=0;i<3;i++)
  { for(j=0;j<5;j++)
  s=s+a[j];
  v=s/5;
  s=0;
  }
  l=(v[0]+v[1]+v[2])/3;
  printf("math:%d\nc languag:%d\ndbase:%d\n",v[0],v[1],v[2]);
  printf("total:%d\n",l);
}
初始化的额外说明:
  对于二维数组初始化赋值还有以下说明:
  1.可以只对部分元素赋初值,未赋初值的元素自动取0值。
  例如: static int a[3][3]={,,}; 是对每一行的第一列元素赋值,未赋值的元素取0值。 赋值后各元素的值为: 1 0 02 0 03 0 0
  static int a [3][3]={{0,1},{0,0,2},}; 赋值后的元素值为 0 1 00 0 23 0 0
  2.如对全部元素赋初值,则第一维的长度可以不给出。
例如: static int a[3][3]={1,2,3,4,5,6,7,8,9}; 可以写为:static int a[][3]={1,2,3,4,5,6,7,8,9};

 


 数组的操作
我们这里主要介绍一维数组的基本操作,至于二位数组的操作与一维数组基本一致,而且二维数组的操作用的很少,所以在这里我们不会做很详细的介绍。
 数组中的排序算法
交换排序
交换排序包含冒泡排序(bubble sort)和快速排序(quicksort)。选择排序包含shaker排序和堆排序(heapsort)。在这里我们只介绍冒泡排序这也是我们数组排序运用最多最为广泛的排序方法。
冒泡排序的基本思想:

冒泡排序(BubbleSort)的基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。
由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。

这里我们不做过多的文字描述了,我们来看一个程序实例:bubble_sort.c
 
 

 

运行结果:

 

选择排序
基本思想:
每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
这里我们还是来看实例,注意一下,下面我们这个程序来用ubuntu下安装的eclipse来开发这个程序,下面我们来看:switch_sort.c
我们打开eclipse,在新建工程里选择其他:
 

 

选择C工程:

 

 

注意这里你必须事先安装了eclipse的CDT插件,当然你也可以直接下载安装eclipse的C/C++开发包,
创建项目:
 

 

编辑代码:

 

 

运行结果:

 

 

数组中的排序算法还有很多,这里我们不可能都去介绍,上面我们已经给大家介绍了两种较为常用的数组的排序算法。

 数组中的查找算法
 遍历查找
这种查找算法是最普通的查找算法,也是实现最为简单的,同时也是相当实用的,在我们不知道待查找的数组是否有序的情况下,用此算法相当常见,虽然此算法显得有些笨拙,但是很容易使用。
基本思想:思想也很简单,就是遍历所有,寻找与之符合的元素即可。该算法一般用于本来无序的序列。
查找一般有几种情况,查找特定元素、查找最大元素、查找最小元素等。而且查找一般情况下我们需要的结果都有两种,是否存在?在什么位置?
这样我们来举两个例子:
查找一个数组中的特定元素,返回该元素的位置,我们设定返回-1时,说明不存在。
我们创建find_ele.c文件:
 

 

我们输入:669 运行结果为

 

 

 

下面我们来看查找一个数组中的最大元素,返回这个最大元素,创建find_max.c

 

 

运行结果为:

 

 折半查找
基本思想:
折半查找的算法思想是将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。通过一次比较,将查找区间缩小一半。 折半查找是一种高效的查找方法。它可以明显减少比较次数,提高查找效率。但是,折半查找的先决条件是查找表中的数据元素必须有序。


算法描述:
step1. 首先确定整个查找区间的中间位置
  mid = ( left + right )/ 2
  step2. 用待查关键字值与中间位置的关键字值进行比较;
  若相等,则查找成功
  若大于,则在后(右)半个区域继续进行折半查找
  若小于,则在前(左)半个区域继续进行折半查找
  Step3. 对确定的缩小区域再按折半公式,重复上述步骤。最后,得到结果:要么查找成功, 要么查找失败。
折半查找的存储结构采用一维数组存放。

下面我们还是来看实例,创建binsearch.c
 

 

 

运行结果为:

 

 

 


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章