C语言day07(排序、二维数组、指针)

【1】冒泡排序

int  a[5] = {5,4,3,2,1};

1》概念

相邻的两个数进行比较(两两比较),如果前者大就交换位置

2》排序思想

第一轮:

5  4  进行比较  前者大   交换 ——>    4  5  3  2  1

5  3  进行比较  前者大  交换 ——>     4  3  5  2  1

5  2  进行比较  前者大  交换 ——>     4  3  2  5  1    

5  1  进行比较  前者大  交换 ——>     4  3  2  1  5

第二轮:

4  3  进行比较  前者大   交换 ——>    3  4  2  1  5

4  2  进行比较  前者大   交换 ——>    3  2  4  1  5

4  1  进行比较  前者大   交换 ——>    3  2  1  4  5      // 4 在前面和 5 已经交换过了,不用再交换了

第三轮:

3  2  进行比较  前者大   交换 ——>    2  3  1  4  5

3  1  进行比较  前者大   交换 ——>    2  1  3  4  5    // 3 在前面和 4 、5 都已经交换过了,不用再交换了

第四轮:

2  1  进行比较  前者大   交换 ——>    1  2  3  4  5   //2 在前面和 3 、4 、5 都已经交换过了,不用再交换了

3》规律

交换的轮数(外层循环):由数组的元素个数决定,轮数 = 元素个数 -1

每一轮交换的次数(内层循环):也是由数组元素个数决定,次数 = 元素个数 - 1 - 外层循环变量

4》代码展示

#include <stdio.h>

int main(){
    int a[5] = {2,4,2,8,3};
    int i,j;
    int n = sizeof(a) / sizeof(int);
    for(i = 0;i < n;i++){
        printf("%d ",a[i]);
    } 
    printf("\n");
    for(i = 0;i < n - 1;i++)
    for(j = 0;j < n - 1 - i;j++){
        if(a[j] > a[j+1]){
            int t = a[j];
            a[j] = a[j+1];
            a[j+1] = t;
        }
     }

    for(i = 0;i < n;i++){
        printf("%d ",a[i]);
    }
    printf("\n");
    return 0;
}

5》运行结果

【2】选择排序

1》概念

在n个数中找最小值的下标暂时存储,和正确位置交换

2》排序思想

int  a[5] = {5,4,3,2,1};

找最小值

第一轮:

将第一个数暂定为最小值,下标 k 设为0 k = 0  a[k] = 5                          5(k)  4  3  2  1                  

a[k] = 5  a[1] = 4  比较  4小于5  把 4 的下标赋给 k    k = 1  a[k] = 4        5  4(k)  3  2  1

a[k] = 4  a[2] = 3  比较  3小于4  把 3 的下标赋给 k    k = 2  a[k] = 3        5  4  3(k)  2  1

a[k] = 3  a[3] = 2  比较  2小于3  把 2 的下标赋给 k    k = 3  a[k] = 2        5  4  3  2(k)  1

a[k] = 2  a[4] = 1  比较  1小于2  把 1 的下标赋给 k    k = 4  a[k] = 1        5  4  3  2  1(k)

这时 k 下标所代表的值就是最小的值,把这个值和最前面的值进行交换   1  4  3  2  5

第二轮:

将第二个数暂定为最小值,下标 k 设为 1  k = 1  a[k] = 4                         1  4(k)  3  2  5

a[k] = 4  a[2] = 3  比较  3小于4  把3的下标赋给k     k = 2  a[k] = 3           1  4  3(k)  2  5

a[k] = 3  a[3] = 2  比较  2小于3  把2的下标赋给k     k = 3  a[k] = 2           1  4  3  2(k)  5

a[k] = 2  a[4] = 5  比较  5 大于2 下标不用改变         k = 3  a[k] = 2           1  4  3  2(k)  5

这时 k 下标所代表的数就是该轮最小的值,把这个值和该轮最前面的值进行交换   1   3    5

第三轮:

将第三个数暂定为最小值,下标 k 设为 2  k = 2  a[k] = 3                          1  2  3(k)  4  5

a[k] = 3  a[3] = 4  比较  4大于3  下标不用改变         k = 2  a[k] = 3           1  2  3(k)  4  5

a[k] = 3  a[4] = 5  比较  5大于3  下标不用改变         k = 2  a[k] = 3           1  2  3(k)  4  5

这时 k 下标所代表的数就是该轮最小的值,下标没变,不用进行交换      1  2  3  4  5

第四轮:

将第三个数暂定为最小值,下标 k 设为 3  k = 3  a[k] = 4                          1  2  3  4(k)  5

a[k] = 4  a[4] = 5  比较  5大于4  下标不用改变         k = 3  a[k] = 4           1  2  3  4(k)  5

这时 k 下标所代表的数就是该轮最小的值,下标没变,不用进行交换      1  2  3  4  5

3》规律

交换的轮数(外层循环):由数组的元素个数决定,轮数 = 元素个数 - 1

每轮交换的次数(内层循环):该轮要比较的元素个数,次数 = 元素个数 - 1 - 外层循环变量

4》代码展示

    #include<stdio.h>
    int main(){
    int a[5] = {5,6,3,1,2};
    int i,j;
    int n = sizeof(a) / sizeof(int);
    for(i = 0;i < n - 1;i++){
        int k = i;
        for(j = i + 1; j < n;j++){
            if(a[k] > a[j]){
                k = j;
            }
        }
        if(k != i){
        int t = a[k];
        a[k] = a[i];
        a[i] = t;
        }
    }
    for(i = 0;i < n;i++){
        printf("%d ",a[i]);
    }
    return 0;
}

5》运行结果

【3】冒泡排序和选择排序的区别

共同点

1)都有两层循环,外层循环控制比较的轮数,和数组元素的个数有关,内层循环控制需要参与比较的元素个数,和外层循环的轮数有关
2)两种算法进行交换的结构是相同的。
3)两种算法虽然效率不一样,但是最终比较的次数是一样的

不同点

冒泡排序第一轮交换完成最大最后;选择排序第一轮结束最前

【4】二维数组

1》格式

存储类型    数据类型    数组名[行数][列数]

例:int arr[2][3];    //两行三列的二维数组
    int arr[2][3] = {1,2,3,4,5,6};

2》访问

数组名[行下标][列下标]

第 1 行第 1 列   第一个元素 :arr[0][0]        行下标和列下标都是从零开始

第 2 行第 3 列元素:arr[1][2]     arr[行数 - 1][列数 - 1]

行和列都不能越界

int arr[][3] = {1,2,3,4,5,6,7};    //正确
int arr[2][] = {1,2,3,4};          //错误

二维数组定义时行数可以省略,但是列数不能省略

3》数组的元素个数

元素个数 = 行数 * 列数

4》数组大小

1)数组大小 = 行数 * 列数 *数据类型的大小

2)sizeof(数组名)

5》数组名

数组名  arr:第一行的首地址

arr + 1:第二行的首地址

arr [0]:第一行第一列的首地址

6》初始化

1)全部初始化

int arr[2][3] = {1,2,3,4,5,6};         //顺序赋值
int arr[2][3] = {{1,2,3},{4,5,6}};     //按行赋值

2)部分初始化: 未赋值的部分自动初始化为0

int arr[2][3] = {1,2,3,4};      //顺序赋值  123400
int arr[2][3] = {{1,2},{4}};    //按行赋值  120400

3)未初始化:所有的值都是随机值,后期赋值单独进行

int arr[2][3];
arr[0][0] = 1;arr[0][1] = 1;     //单独赋值

7》二维数组的遍历

双重for循环 : 外层循环控制行,内层循环控制列

练习:

在终端输入一个3行3列的数,并输出

#include <stdio.h>
int main(){
int arr[3][3] = {};
    for(int i = 0;i < 3;i++){
        for(int j = 0;j < 3;j++){
            scanf("%d",&arr[i][j]);
        }
    }
    for(int i = 0;i < 3;i++){
        for(int j = 0;j < 3;j++){
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }


    return 0;
}

练习:

有一个3x4的矩阵(元素值不相同),要求输出其中最大值以及它的行号和列号

#include <stdio.h>
int main(){
    int a[3][4] = {1,2,3,4,1,0,76,4,34,2,34,56};
    int max = a[0][0];
    int hang,lie;
    for(int i = 0;i < 3;i++){
        for(int j = 0;j < 4;j++){
             if(max < a[i][j]){
                max = a[i][j];
                hang = i + 1;
                lie = j + 1;
             }
        }
    }
    printf("max = %d hang = %d lie = %d\n",max,hang,lie);
    return 0;
}

 【5】指针

指针就是地址

地址:内存空间每一个单元格的编号(门牌号)

指针:就是地址,内存地址

指针变量:存储指针的变量

1》指针变量

格式:存储类型    数据类型    *   指针变量名

int *p;         //定义了一个指针变量p
int a = 10;
int *p = &a;   //p中存储的是a的地址

访问值:*p指针变量名  *p

修改值:*指针变量名 = 新值

    int a = 10;
    int *p = &a;
    printf("%d\n",*p);       //访问指针变量的值
    *p = 200;                //修改指针变量的值
    printf("%d\n",*p);

指针和变量之间的关系

指针就是地址

指针变量也还是一个变量,在定义创建一个指针变量时,它也会开辟一个内存空间去存储这个变量

当你将 a 的地址赋给指针变量 p 时,指针变量 p 存的就是 a 的地址,变量 a 里面存的是它的值 10

这两个变量他们都有自己的内存空间

如果你再对指针变量 p 进行取地址  &p  那么得到的就是指针变量 p 的内存地址

2》指针操作符

*  :取内容(解引用)

&  :取地址

单目运算:从右往左

int a = 10;

*&a;     //10   *   &两者互逆

&*a;    //错误

3》初始化

1)将普通变量赋值给指针
int a=20;

int *p=&a;//定义时赋值

int *p;//未赋值   野指针

int *p=NULL;

int b=10;

p=&b;//先定义后赋值
2)将数组的地址赋值给指针
char s[]="hello";

char *p=s;
3)将指针变量的值交给另一个指针变量
int a=20;

int *p=&a;

int *q=p;

练习:

编写一个程序,找出1000以内所有的完数,所谓完数就是一个数恰好等于它的因子之和,

例如6=1+2+3,6就是一个完数。28也是 28=1+2+4+7+14。

#include <stdio.h>

int main(){
    int i,j;
    for(i = 1;i <= 1000;i++){
        int a = 0;
        for(j = 1;j < i;j++){
            if(i % j == 0){
               a += j;
            }
        }
        if(i == a){
           printf("%d ",a);
        }
    }
    return 0;
}

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值