一、排序算法
排序也称排序算法(Sort Algorithm),排序是将一组数据,依指定的顺序进行排列的过程。
排序的分类:
(1)内部排序:指将需要处理的所有数据都加载到内部存储器(内存)中进行排序。
(2)外部排序法:数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。
冒泡排序
(1)冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。
(2)因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志 flag 判断元素是否进行过交换。从而减少不必要的比较。
冒泡排序实例
我们将五个无序的数:{3,9,-1,10,-2}使用冒泡排序法将其排成一个从小到大的有序数列。
#include<stdio.h>
//冒泡排序的函数
void bubbleSort(int arr[],int arrLen){
//用 for 循环,循环比较排序
int i,j;
int temp;//临时变量
for(i=0;i<arrLen-1;i++){
for(j=0;j<arrLen-i-1;j++){
//如果前面的一个数较大就交换
if(arr[j]>arr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
void main(){
int arr[]={3,9,-1,10,-2,-11};
int arrLen=sizeof(arr)/sizeof(int);//计算得到数组元素的个数
int i;
bubbleSort(arr,arrLen);//默认是地址传递
printf("\n排序后:\n");
for(i=0;i<arrLen;i++){
printf(" %d",arr[i]);
}
}
问题升级,用键盘输入n个数,使用冒泡排序法将其排成一个从小到大的有序数列。
#include<stdio.h>
//冒泡排序的函数
void bubbleSort(int arr[],int n){
//用 for 循环,循环比较排序
int i,j;
int temp;//临时变量
for(i=0;i<n-1;i++){
for(j=0;j<n-i-1;j++){
//如果前面的一个数较大就交换
if(arr[j]>arr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
void main(){
printf("请输入数组的元素个数:");
int n;
scanf("%d",&n);
printf("请输入数组的%d个元素:",n);
int arr[n];
int i;
for(i=0;i<=n;i++){//循环输入
if(i<n){
scanf("%d",&arr[i]);
}
else{//输入第n个数结束循环
break;
}
}
bubbleSort(arr,n);//默认是地址传递
printf("\n排序后:\n");
int j;
for(j=0;j<n;j++){
printf(" %d",arr[j]);
}
}
二、查找
在C中,我们常用的查找有两种:
(1)顺序查找
(2)二分查找
案例演示
顺序查找:有一个数列{23,1,34,89,101}猜数游戏:从键盘中任意输入一个数,判断数列中是否包含该数。
要求:如果找到了,就提示 找到了,并给出下标,找不到提示 没有。
思路:创建数组,输入一个元素,遍历数组,如果相等就输出找到了和它的下标。
#include<stdio.h>
int seqSearch(int arr[],int arrLen,int val){
int i;
for(i=0;i<arrLen;i++){
if(arr[i]==val){
return i;
}
}
//如果在 for 循环中,没有返回return,说明没有找到
return -1;
}
void main(){
int n;//要找的元素
scanf("%d",&n);
int arr[]={23,1,34,89,101};
int arrLen=sizeof(arr)/sizeof(int);
int index=seqSearch(arr,arrLen,n);
if(index != -1){
printf("找到了 下标为:%d",index);
}
else{
printf("没有");
}
}
输入101
输入102
二分查找:请对一个有序数组进行二分查找{1,8,10,89,1000,1234},输入一个数看看该数组是否存在此数,并且求出下标,如果没有就提示"没有这个数"。
二分查找的前提是该数组是一个有序数组。
- 思路分析:比如我们要查找的数是findVal。
- 先找到数组中间这个数 midVal,和findVal比较。
- 如果midVal > findVal 说明,应该在midVal的左边查找。
- 如果midVal < findVal 说明,应该在midVal 的右边查找。
- 如果midVal == findVal,说明找到。
//二分查找的前提是该数组是一个有序数组
// binarySearch 定义的二分查找函数名
#include<stdio.h>
int binarySearch(int arr[],int leftIndex,int rightIndex,int findVal){
//先找中间值 midVal
int midIndex =(leftIndex + rightIndex)/2;
int midVal = arr[midIndex];
//如果 leftIndex > rightIndex, 说明这个数组比过,没有找到
if(leftIndex > rightIndex){
return -1;
}
if(midVal > findVal){
binarySearch(arr,leftIndex,midIndex-1,findVal);
}
else if(midVal < findVal){
binarySearch(arr,midIndex+1,rightIndex,findVal);
}
else{
return midIndex;
}
}
void main(){
int arr[]={1,8,10,89,1000,1234};
int arrLen=sizeof(arr)/sizeof(int);
int n;
scanf("%d",&n);
int index=binarySearch(arr,0,arrLen-1,n);
if(index !=-1){
printf("找到了 下标为:%d",index);
}
else{
printf("没有");
}
}
输入1000
输入500
三、多维数组
二维数组:
案例1:请用二维数组输出如下图形
0 0 0 0 0 0
0 0 1 0 0 0
0 2 0 3 0 0
0 0 0 0 0 0
使用方式1:先定义在初始化
语法:类型数组名[大小][大小];
比如: int a[2][3];
二维数组在内存的存在形式,各个元素的地址是连续分布的,即在前一个元素基础上+4。
#include<stdio.h>
void main(){
int a[4][6];//表示一个4行6列的二维数组
int i,j;
//全部初始化为0
//不初始化,全是分配的垃圾值
for(i=0;i<4;i++){
for(j=0;j<6;j++){
a[i][j]=0;
}
}
a[1][2]=1;//给第 2 行第 3 列的那个位置赋值为 1
//行和列都是从 0 开始的
a[2][1]=2;
a[2][3]=3;
//输出二维数组
for(i=0;i<4;i++){
for(j=0;j<6;j++){
printf("%d",a[i][j]);
}
printf("\n");
}
}
使用方式2:直接初始化
(1)定义类型数组名 [大小] [大小]={{值1,值2..},{值1,值2..},{值1,值2..};
(2)或者类型数组名 [大小] [大小]={值1,值2,值3,值4,值5,值 6 ..};
int[4][6]={
{0,0,0,0,0,0}
{0,0,1,0,0,0}
{0,2,0,3,0,0}
{0,0,0,0,0,0}
};
int[4][6]={0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,3,0,0,0,0,0,0,0,0}//自动匹配到各行各列
案例2:请使用灵活的方式遍历如下数组
int map[3][3]={{0,0,1},{1,1,1},{1,1,3}};
#include<stdio.h>
void main(){
int map[3][3]={{0,0,1},{1,1,1},{1,1,3}};
printf("%d\n",sizeof(map));//得到 map 数组的大小 4*9
printf("%d\n",sizeof(map[0]));// 得到 map 数组第1行有多大 3*4
int rows = sizeof(map)/sizeof(map[0]);// 得到多少行 3
printf("%d\n",rows);
int clos = sizeof(map[0])/sizeof(int);//得到列 3
printf("%d\n",clos);
}
案例3:遍历该二维数组,并得到和
int arr[3][2]={{4,6},{1,4},{-2,8}};//遍历该二维数组,并得到和
#include<stdio.h>
void main(){
int i,j;
int sum=0;
int arr[3][2]={{4,6},{1,4},{-2,8}};
for(i=0;i<=2;i++){
for(j=0;j<=1;j++){
printf("%d ",arr[i][j]);//取出每一个数
sum += arr[i][j];//相加
}
printf("\n");
}
printf("sum = %d",sum);
}
例题
1.比如我们开发一个五子棋游戏,棋盘就是需要二维数组来表示。
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
#include<stdio.h>
void main(){
int a[6][6];
int i,j;
for(i=0;i<6;i++){
for(j=0;j<6;j++){
if((i+1)%2 != 0 && (j+1)%2 != 0){
printf("%d ",a[i][j]=0);
}
else if((i+1)%2 == 0 && (j+1)%2 == 0){
printf("%d ",a[i][j]=0);
}
else{
printf("%d ",a[i][j]=1);
}
}
printf("\n");
}
}
2.定义二维数组,用于保存三个班,每个班五名同学成绩,并求出每个班级平均分、以及所有班级平均分。
#include<stdio.h>
void main(){
double scores[3][5];
int i,j;
double TScores = 0.0; //所有班总成绩
double CTScores = 0.0; //各班总成绩
for(i=0;i<3;i++){
for(j=0;j<5;j++){
scores[0][0]=0.0;
}
}
for(i=0;i<3;i++){
for(j=0;j<5;j++){
printf("请输入第 %d 个班的第 %d 个学生成绩:",i+1,j+1);
scanf("%lf",&scores[i][j]);
}
}
//统计各班总成绩 和 所有学生总成绩
for(i=0;i<3;i++){
double CTScores = 0.0;//每一个班后都清零
for(j=0;j<5;j++){
CTScores += scores[i][j];//累加每个班的总成绩
}
printf("\n 第 %d 个班的平均成绩是:%.2f",i+1,CTScores/3);
TScores += CTScores;//每一个班总成绩累加得到所有学生总成绩
}
printf("\n 所有学生总成绩:%.2f 平均成绩:%.2f",TScores,TScores/15);
}
二维数组使用细节和注意事项
(1)可以只对部分元素赋值,未赋值的元素自动取“零”值。
#include<stdio.h>
void main(){
int a[4][5]={{1},{2},{3},{4}};
int i,j;
for(i=0;i<4;i++){
for(j=0;j<5;j++){
printf("%d",a[i][j]);
}
printf("\n");
}
}
(2)如果对全部元素赋值,那么第一维的长度可以不给出。
int a[3][3]={1,2,3,4,5,6,7,8,9};
也可以写成
int a[][3]={1,2,3,4,5,6,7,8,9};
(3)==二维数组可以看作是由一维数组嵌套而成的:==如果一个数组的每个元素又是一个数组,那么它就是二维数组。
二维数组a[3][4]可看成三个一维数组,它们的数组名分别为a[0]、a[1]、a[2]。
这三个一维数组都有4个元素,如:一维数组a[0]的元素为 a[0][0]、a[0][1]、a[0][2]、a[0][3]。
综合体:创建一个 4*4 的数组,提示从键盘依次输入数组的各元素,之后求该数组所有元素之和、对角线元素之和,以及最大元素。(提示:可以使用两层 for 循环嵌套实现)
#include<stdio.h>
void main(){
int i,j;
int sum=0;
int sum1=0;
int max=0;
int temp=0;
int arr[4][4];//定义数组
for(i=0;i<4;i++){//循环输入
for(j=0;j<4;j++){
printf("请输入第 %d 行的第 %d 列:",i+1,j+1);
scanf("%d",&arr[i][j]);
}
}
//遍历读取每一个数
for(i=0;i<4;i++){
for(j=0;j<4;j++){
printf("%d ",arr[i][j]);//取出每一个数
sum += arr[i][j];//相加
//对角线和
if(i==j || i==3-j){
sum1 += arr[i][j];
}
//找最大数
if(arr[i][j] > max){
max = arr[i][j];
}
}
printf("\n");
}
printf("sum = %d\nsum1= %d\nmax=%d",sum,sum1,max);
}