两种简单的排序方法二维数组
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] 交换
排序过程:
- 首先通过n-1次比较,从n个数中找出最小值的下标,将它与第一个数交换,第一轮选择排序,结果最小值被放在第一个元素的位置上
- 再通过n-2次比较,从剩余的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;
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进行比较,满足条件则进行值交换。