排序和查找

排序和查找

1. 排序算法介绍

  • 排序也称排序算法,排序是将一组数据,依指定的顺序进行排列的过程
  • 排序的分类
    • 内部排序:指将须要处理的全部数据都加载到内部存储器(内存)中进行排序
    • 外部排序:数据量过大,没法所有加载到内存中,须要借助外部存储器进行排序

2. 冒泡排序

2.1 基本介绍

  • 冒泡排序的基本思想是:经过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素从前移向后部,就像水底的气泡同样逐渐向上冒。
  • 由于排序的过程当中,各元素不断接近本身的位置,若是一趟比较下来没有进行过交换,就说明序列有序,所以要在排序过程当中设置一个标志flag判断元素是否进行过交换,从而减小没必要要的比较

2.2 案例

  • 将五个无序 的数:{3,9,-1,10,-2}使用冒泡排序法将其排成一个从小到大的有序数列

2.3 分析冒泡的过程+代码

//冒泡排序的过程(从小到大)
原始数组{3,9,-1,10,-2}

第一轮
    1.3,9,-1,10,2
    2.3,-1,9,10,2
    3.3,-1,9,10,2
    4.3,-1,9,-2,10
    //第一大的数就移动到最后
第二轮
    1.-1,3,9,-2,10
    2.-1,3,9,-2,10
    3.-1,3,-2,9,10
第三轮
    1.-1,3,-2,9,10
    2.-1,-2,3,9,10
 第四轮
    -2,-1,3,9,10
#include<stdio.h>
//冒泡排序函数
void bubbleSort(int arr[],int arrLen){
    //由于每轮排序几乎同样,所以,可使用for循环处理
    int i,j;
    int t;//临时变量
    for(i=0;i<arrLen-1;i++){
        for(j=0;j<arrLen-1-i;j++){
        //若是前面的数大于后面的数,就交换
        if(arr[j]>arr[j+1]){
            t=arr[j];
            arr[j]=arr[j+1];
            arr[j+1]=t;
        }
        }
    }
}
void main(){
    int arr[]={3,9,-1,10,-2,11};
    int arrLen=sizeof(arr)/sizeof(int);
    int j;
    bubbleSort(arr,arrLen);//数组默认是地址传递
    printf("排序后");
    for(j=0;j<arrLen;j++){
        printf("%d",arr[j]);
    }
    getchar();
}

3. 查找

3.1 介绍

在C中,经常使用的查找有两种算法

  • 顺序查找
  • 二分查找

3.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 arr[]={23,1,34,89,101};
    int arrLen=sizeof(arr)/sizeof(int);
    int index=seqSearch(arr,arrLen,-101);
    if(index != -1){
        printf("找到 下标为%d",index);
    }else{
        printf("没有找到");
    }
    getchar();
}
  • 请对一个有序数组进行二分查找{1,8,10,89,100,123},输入一个数看看该数组是否存在此数,而且求出下标,若是没有就提示“没有这个数”
  • 二分查找的前提是该数组是一个有序数组
#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;
    }
    //若是midVal>findVal说明,应该在midVal的左边查找
    if(midVal>findVal){
        binarySearch(arr,leftIndex,midIndex-1,findVal);
    }else if(midVal<findVal){
        //若是midVal<findVal说明,应该在midVal的右边查找
        binarySearch(arr,midIndex+1,rightIndex,findVal);
    }else{
        return midIndex;
    }
}

void main(){
    //分析
    //好比要查找的数是findVal
    //1.先找到数组中间这个数midVal,和findVal比较
    //2.若是midVal>findVal说明,应该在midVal的左边查找
    //3.若是midVal<findVal说明,应该在midVal的右边查找
    //4.若是midVal==findVal,说明找到
    int arr[]={1,8,10,89,1000,1234};
    int arrLen=sizeof(arr)/sizeof(int);
    int index=binarySearch(arr,0,arrLen-1,-1000);
    if(index!=-1){
        printf("找到index=%d",index);
    }else{
        printf("没有找到");
    }
    getchar();
}

4.多维数组和二维数组

多维数组主要介绍二维数组数组

5. 二维数组的应用场景

好比开发一个五子棋游戏,棋盘就是须要二维数组来表示函数

6.二维数组的使用

6.1 快速入门

请用二维数组输出以下图形布局

0 0 0 0 0 0code

0 0 1 0 0 0排序

0 2 0 3 0 0游戏

0 0 0 0 0 0内存

6.2 使用方式1:先定义再初始化

语法:类型 数组名[大小 ] [大小]开发

好比:int a[2] [3]get

6.3 使用演示

二维数组在内存的存在形式,各个元素的地址是连续分布的,即在前一个元素基础上加+4

#include<stdio.h>
void main(){
    //a[4][6];表示一个4行6列的二维数组
    int a[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;
    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");
    }
    //看看二维数组的内存布局
    printf("二维数组a的首地址=%p",a);
    printf("二维数组a[0]的地址=%p",a[0]);
    printf("二维数组a[0][0]的地址=%p",&a[0][0]);
    printf("二维数组a[0][1]的地址=%p",&a[0][1]);
    //将二维数组的各个元素的地址输出
    printf("\n");
    for(i=0;i<4;i++){
        printf("a[%d]的地址=%p",i,a[i]);
        for(j=0;j<6;j++){
            printf("a[%d][%d]的地址=%p",i,j,&a[i][j]);
        }
        printf("\n");
    }
    getchar();
}

6.4 使用方式2:直接初始化

  • 定义 类型 数组名【大小】【大小】={{值1,值2....},{值1,值2....}};
  • 或者 类型 数组名 【大小】【大小】 ={值1,值2,值3,值4,值5,值6...};
    • 会自动匹配到各行各列

7.二维数组应用案例

7.1 案例1

  • 请使用灵活的方式遍历以下数组
  • int map[3] [3]={{0,0,1},{1,1,1}{1,1,3}};

7.2 案例2

int arr[3] [2]={{4,6},{1,4},{-2,8}};

遍历该二维数组,并获得和

#include <stdio.h>
void main(){
    int map[3][3]={{0,0,1},{1,1,1},{1,1,3}};
    //遍历
    //先获得行
    //1.sizeof(map) 获得这个map数组的大小9*4=36
    //2.sizeof(map[0])获得map中,第一行有多大3*4=12
    int rows=sizeof(map)/sizeof(map[0]);
    //printf("rows=%d",rows);
    //获得列
    int cols=sizeof(map[0])/sizeof(int);
    int i,j,sum=0;
    for(i=0;i<rows;i++){
        for(j=0;j<cols;j++){
            printf("%d",map[i][j]);
            sum+=map[i][j];
        }
        printf("\n");
    }
    printf("sum=%d",sum);
    getchar();
}

7.4 定义二维数组,用于保存三个班,每一个班五名同窗成绩,并求出每一个班级平均分,以及全部班级平均分

#include<stdio.h>
void main(){
    //分析
    //1.建立一个scores[3][5]
    //2.遍历,给复制
    //3.再次遍历,统计总分和平均分
    //4.输出
    double score[3][5];
    int rows=sizeof(score)/sizeof(score[0]),cols=sizeof(score[0])/sizeof(double),i,j;
    //classTotalScore 各个班级总成绩 totalscore 全部学生成绩
    double totalScore=0.0,classTotalScore=0.0;
    for(i=0;i<rows;i++){
        for(j=0;j<rows;j++){
            score[i][j]=0.0;
        }
    }
    //遍历,给每一个学生输入成绩
    for(i=0;i<rows;i++){
        for(j=0;j<cols;j++){
            printf("请输入第%d个班的第%d个学生的成绩",i+1,j+1);
            scanf("%lf",&score[i][j]);
        }
    }
    getchar();
    //显示下成绩状况
    for(i=0;i<rows;i++){
        for(j=0;j<cols;j++){
            printf("%.2f",score[i][j]);
        }
        printf("\n");
    }
    //统计各个班的总成绩,和全部学生的成绩
    for(i=0;i<rows;i++){
        classTotalScore=0.0;//每次清零
        for(j=0;j<cols;j++){
            classTotalScore+=score[i][j];//累计每一个班的总成绩
        }
        printf("第%d个班的平均成绩是%.2f",i+1.classTotalScore/cols);
        totalScore+=classTotalScore;//将该班的总分,累加到totalScore
    }
    printf("全部学生的总成绩是%.2f 平均成绩是%.2f",totalScore,totalScore/(rows*cols));
    getchar();
    getchar();
}

8.二维数字使用细节和注意事项

  • 能够只对部分元素赋值,为赋值的元素自动取零
int main(){
    int a[4][5]={{1},{2},{3},{1}};
    int i,j;
    for(i=0;i<4;i++){
        for(j=0;j<5;j++){
            printf("%d",a[i][j]);
        }
        printf("\n");
    }
    getchar();
}
  • 若是对所有元素赋值,那么第一维的长度能够不给出
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};
  • 二维数组能够看做是由一维数组嵌套而成的;若是一个数组的每一个元素又是一个数组,那么它就是二维数组
    • 二维数组a[3] [4]可当作三个一维数组,他们数组名分别为a[0],a[1],a[2]
    • 这三个一维数组都有4个元素,如一维数组a[0]的元素为a[0] [0],a[0] [1],a[0] [2],a[0] [3]
相关文章
相关标签/搜索