C语言基础7——两种简单排序算法和二维数组

发布于:2025-07-23 ⋅ 阅读:(20) ⋅ 点赞:(0)

两种简单的排序方法二维数组

1. 排序

1.1 冒泡排序

冒泡排序,顾名思义,像水中的鱼吐泡泡,一点点的把最小(或最大)的数一步步的从水里一点点的冒出水外的过程。
思想:两两比较,第j个和j+1个比较,若满足大小关系,则交换两个数的位置。需要用到两轮for循环,一层遍历整个数组,将所有的数排序,内层是比较大小的时候进行值的交换。
int a[5] = {5, 4, 3, 2, 1};将数组a进行升序。

第一轮: i = 0
j = 0         4 5 3 2 1        //第j和第j+1个元素进行比较,即5和4进行比较,前面比后面的大则交换。
j = 1         4 3 5 2 1        //j变为1,第2和第3个元素进行比较,满足大小关系则交换。
j = 2         4 3 2 5 1        //同上,以下同理。
j = 3         4 3 2 1
5

第二轮: i = 1
j = 0         3 4 2 1 5
j = 1         3 2 4 1 5
j = 2         3 2 1
4 5

第三轮: i = 2
j = 0         2 3 1 4 5
j = 1         2 1
3 4 5

第四轮: i = 3
j = 0         1
2 3 4 5

总结:n个数:比较的n-1轮,每一轮交换的次数是n-1此开始依次递减的

#include <stdio.h>
#include <string.h>
#define N 5        //宏定义,全局变量,不会在主函数中被改变

int main()
{
    int arr[N] = {5, 4, 3, 2, 1};
    int temp;//用于交换中间的变量

    for(int i = 0 ; i < N - 1 ; i ++)    //交换的轮数
    {    
        for(int j = 0 ; j < N - 1 - i ; j ++)    //    每一轮交换的次数
        {
            if(arr[j] > arr[j + 1])
            {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    
    for(int i = 0 ; i < N ; i ++)
    {
        printf("%d", arr[i]);
    }
    
    putchar(10);

    return 0;
}

练习1:将10个数进行冒泡排序,以降序的方式(参考代码见本文章最后)

1.2 选择排序

n个数:先找出最小值的下标暂存,选择出最小的值与arr[i] 交换

排序过程:

  1. 首先通过n-1次比较,从n个数中找出最小值的下标,将它与第一个数交换,第一轮选择排序,结果最小值被放在第一个元素的位置上
  2. 再通过n-2次比较,从剩余的n-1个数中找出最小值的下标做记录,将它与第二个数交换,第二轮排序
  3. 重复上述过程,共经过n-1轮排序后,排序结束
#include <stdio.h>
#include <string.h>
#define N 5

int main()
{
    int arr[N] = {5, 4, 3, 2, 1};
    int temp;
    int k;
    
    for(int i = 0 ; i < N - 1 ; i ++)
    {
        k = 1;
        for(int j = i + 1 ; j < N ; j++)
        {
            if(arr[j] < arr[k])
                k = j;
        }
        
        if(i != k)
        {
            temp = arr[k];
            arr[k] = arr[i];
            arr[i] = temp;
        }
    }

    for(int i = 0 ; i < N ; i++)
    {
        printf("%d\t", arr[i]);
    }
    
    printf("\n");

    return 0;
}

2. 二维数组

~1格式

存储类型 数据类型 数组名[行数][列数];
int arr[2][3];

行数可以省略,列数不能省略
int arr[][3];

注意:为什么列数不能省略,这涉及到二维数组在计算机内部的存储形式,可以稍微了解一下,二维数组在内存中按行存储,在一行存完之后会紧接着存储下一行的内容,并且要求二维数组在定义的时候就要将数组的大小确定下来,如果只确定行数,不确定列数,那在二维数组开辟空间的时候,不知道第一行数组的长度,也就无法确定第二行数组的首元素的地址,而确定下二维数组列数之后,可以明确第二行以及之后每一行的首元素地址,且不论首元素是否已经被赋予初值。

~2访问元素

数组名[行下标][列下标]; (下标从0开始)
arr[0][0]:第一行第一列的元素
arr[1][2]:第二行第三列的元素

行下标和列下标都不能越界

~3二维数组的元素个数

行数 * 列数
二维数组的大小 / 数据类型的大小

~4二维数组的大小

sizeof(数组名)
数据类型的大小 * 行数 * 列数

~5数组名

arr:第一行的首地址
arr+1:第二行首地址
arr+n:第n+1行首地址

~6初始化

6.1全部初始化

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

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

#include <stdio.h>

int main()
{
    int arr[2][3] = {1, 2, 3, 4, 5, 6};
    printf("%d %d %d\n", arr[0][0], arr[0][1], arr[0][2]);
    printf("%d %d %d\n", arr[1][0], arr[1][1], arr[1][2]);
    
    return 0;
}

6.2部分初始化:未被初始化的元素值为0

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

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

#include <stdio.h>

int main()
{
    int arr[2][3] = {1, 2, 3, 4};
    printf("%d %d %d\n", arr[0][0], arr[0][1], arr[0][2]);
    printf("%d %d %d\n", arr[1][0], arr[1][1], arr[1][2]);
    
    return 0;
}

6.3未初始化:随机值,需要单独赋值

#include <stdio.h>

int main()
{
    int arr[2][3];
    printf("%d %d %d\n", arr[0][0], arr[0][1], arr[0][2]);
    printf("%d %d %d\n", arr[1][0], arr[1][1], arr[1][2]);
    
    return 0;
}

~7内存分配

arr 和 arr [ 0 ] 并不完全相同,级别不不同,数值上是一样的

arr是行地址

arr[0]是列地址

arr表示第一行的首地址

arr+1表示第二行首地址

arr[0] 表示第一行第一列的地址

arr[0]+1 表示第一行第二列的地址

arr[1] 表示第二行第一列的地址

arr[1]+1 表示第二行第列的地址

~8二维数组遍历

for循环嵌套,外层行数,内层列数

int arr [ m ][ n ] = {};

for(int i = 0; i < m; i++) // 行下标

{

        for(int j = 0; j < n; j++) // 列下标

        {

                scanf(); 或者 printf();

        }

}

// 写一个 for循环嵌套 a[2][3] 从终端输入,并输出,也可以直接初始化,从终端输出

练习2:有一个3x4的矩阵(元素值不相同),要求输出其中最大值以及它的行号和列号(参考代码见本文最后)

------------------------------------------------------这是一条分割线------------------------------------------------------

天才预设的上一篇跳转路径:C语言基础6——数组-CSDN博客

天才预设的下一篇跳转路径:C语言基础8——指针-CSDN博客

天才预设的合集传送路径:C基础_Gu_shiwww的博客-CSDN博客

参考答案

练习1:

将10个数进行冒泡排序,以降序的方式

#include <stdio.h>
#include <string.h>
#define N 10       

int main()
{
    int arr[N] = {5, 4, 3, 2, 1, 45, 34, 78, 23, 43};
    int temp;//用于交换中间的变量

    for(int i = 0 ; i < N - 1 ; i ++)    //交换的轮数
    {    
        for(int j = 0 ; j < N - 1 -i ; j ++)    //    每一轮交换的次数
        {
            if(arr[j] < arr[j + 1])
            {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    
    for(int i = 0 ; i < N ; i ++)
    {
        printf("%d\t", arr[i]);
    }
    
    putchar(10);

    return 0;
}

上文中给到的冒泡排序是升序排序的状态,而本练习题要求降序排列,区别便是主函数内部的循环判断条件。

练习2:

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

#include <stdio.h>

int main()
{
    int arr[3][4] = {12, 23,34,45,56,67,78,89,87,76,54,43};
    int h = 0 , l = 0;                    //行号、列号
    
    //遍历输入
    for(int i = 0 ; i < 3 ; i ++)         //行下标
    {
        for(int j = 0 ; j < 4 ; j ++)     //列下标
        {
            scanf("%d", &arr[i][j]);
        }
    }

    int max = arr[0][0];
    for(int i = 0 ; i < 3 ; i ++)         //行下标
    {
        for(int j = 0 ; j < 4 ; j ++)     //列下标
        {
            if(arr[i][j] >= max)
            {
                max = arr[i][j];
                h = i ;
                l = j ;
            }
        }
    }
    
    printf("最大值=%d, 行号=%d, 列号=%d\n", max, h, l);

    return 0;
}

定义一个中间变量max,用来存放整个二维数组中存放的最大的值,将第一个元素的值赋给max(为什么不将0直接赋值给max,是因为考虑到若二维数组中的元素全部是负数,则0便成为二维数组的最大值,但是二维数组中并不存在0这个元素,所以可以将二维数组中的任意一个值赋值给max,不一定是头元素)然后遍历整个二维数组,与max进行比较,满足条件则进行值交换。


网站公告

今日签到

点亮在社区的每一天
去签到