C语言数组练习——数组置换、数组逆序、冒泡排序(两种方法+图解)

内容

1.数组知识点
2.数组置换
3.数组逆序
4.冒泡排序


*1.数组知识点

数组创建:
type_t arr_name [const_n];
//type_t 是指数组的元素类型
//const_n 必须是一个常量表达式,用来指定数组的大小

int arr1[] = {1,2,3,4};
int arr2[5] = {12345};
int arr3[2]={1};  //不完全初始化
int len = sizeof(arr1) / sizeof(arr1[0]);  //计算数组元素个数,4

一维数组数组名的使用:

  • 计算一维数组元素个数: * sizeof(数组名) / sizeof(数组名[0])
  • 获取数组中一个元素的地址: printf("%p\n", &arr1[3]); //%p 打印格式为指针型 ,指向该数组元素的地址.
  • 可以统计整个数组在内存中所占的长度; // sizeof(数组名) 数组存储在内存中分配的是一段连续的内存空间
  • printf(“一维数组arr1的首地址为:%p\n”, arr1);
  • 数组名是常量,不能进行赋值操作(表达式是不可修改的左值);

注意:
(1) 如果创建数组时,不想直接指定元素个数,就得进行初始化.如果明确了数组元素个数,未进行初始化的元素默认为0; 数组元素下标从0~len-1;
(2) 使用printf()函数打印输出时, %d-格式为整型; %p-格式为指针型,用于打印变量地址; %s-表示打印为字符型;%f-表示打印为浮点型…

char str[]="hello";
char arr[]={'h','e','l','l','o'};
  • sizeof(str)=6 ; 一个字符串数组,在内存中字符串后面隐式包含’ \0’,一个字符占一个字节;
  • strlen(str)=5; arr数组表示含有字符型变量5个单字符的数组;
  • strlen(arr);结果是一个随机数,strlen函数遍历字符串遇到’\0’才会停之;arr数组元素检测完还会继续向后检测,直到遇到’\0’是才终止,因此答案为不确定;

二维数组的创建同理,相当于两个一维数组,多了一维:

int arr1[][2]={0};
int arr2[2][2]={{1,2},{3,4}};

注意:二维数组在创建时不可省略第二维元素个数,也就是不可省略列向量的个数.

  • 计算二维数组行数: sizeof(数组名) / sizeof(数组名[0])
  • 计算二维数组列数: sizeof(数组名[0]) / sizeof(数组名[0][0])
  • 计算二维数组所占内存大小: sizeof(数组名)
  • 计算二维数组第2行所占内存大小: sizeof(数组名[2])
  • 计算二维数组第一行第二列元素地址: &数组名[0][1]
#include<stdio.h>
#include<stdlib.h>

int main() {
	int arr1[] = { 3,4,2,6 };
	int arr2[] = { 9,8,0,1 };
	printf("一维数组arr1的首地址为:%p\n", arr1);
	printf("一维数组arr1[0]元素的地址:%p\n", &arr1[0]);
	printf("一维数组arr1[1]元素的地址:%p\n", &arr1[1]);
	int len1 = sizeof(arr1) / sizeof(arr1[0]);
	int len2 = sizeof(arr2) / sizeof(arr2[0]);
	printf("一维数组arr1的长度为:%d\n", len1);
	printf("一维数组占内存大小:%d\n", sizeof(arr1));
	
	int arr[][3] = { 1,2,3,4,5,6 };
	int row = sizeof(arr) / sizeof(arr[0]);
	int col = sizeof(arr[0]) / sizeof(arr[0][0]);
	printf("二维数组行数%d\n", row);
	printf("二维数组列数%d\n", col);
	printf("二维数组占内存大小:%d\n", sizeof(arr));
	printf("二维数组第一行大小:%d\n", sizeof(arr[0]));
	printf("二维数组第一行地址:%p\n", &arr[0]);
	printf("二维数组第二行第一个元素地址:%p\n", &arr[1][0]);
	
	system("pause");
	return 0;
}

测试结果为:
在这里插入图片描述

*2.数组置换

要求: 将两个相同长度的数组进行元素交换.
(1) 创建两个数组;
(2) 判断两个数组长度是否相等;
(3) 创建一个置换函数,进行数组元素交换.

注意: 数组作为函数参数时,只要传入的实参为数组,实际上传入时,数组名可以隐式转换为指向首元素的指针.所以不管形参是指针型还是数组型,给形参的都是一个指向数组首地址的指针.进行的都是地址传递.

代码实现:

#include<stdio.h>
#include<stdlib.h>

//打印数组序列函数
void printA(int Arr[], int len) {
	for (int i = 0; i < len; i++) {
		printf(" %d ", Arr[i]);
	}
	printf("\n");
}
//交换数组函数:实现两个等长的数组交换
void exchange(int* Arr1, int* Arr2,int len) {
	for (int i = 0; i < len; i++) {
		int temp = Arr1[i];  //老套路,设置中间变量进行交换
		Arr1[i] = Arr2[i];
		Arr2[i] = temp;
	}
}

int main() {
	int arr1[] = { 3,4,2,6 };
	int arr2[] = { 9,8,0,1 };
	int len1 = sizeof(arr1) / sizeof(arr1[0]);
	int len2 = sizeof(arr2) / sizeof(arr2[0]);
	printf("置换前数组arr1的序列为:");
	printA(arr1, len1);
	printf("置换前数组arr2的序列为:");
	printA(arr2, len2);
	if (len1 = len2) {
		exchange(arr1,arr2,len1);
		printf("数组已完成交换\n");
	}
	else {
		printf("数组长度不相同,不能进行交换");
	}
	printf("置换后数组arr1的序列为:");
	printA(arr1,len1);
	printf("置换后数组arr2的序列为:");
	printA(arr2, len2);

	system("pause");
	return 0;
}

结果显示:
在这里插入图片描述

*3.数组逆序

要求:
(1) 创建一个一维数组
(2)通过一个函数令数组改编为原数组的逆序数组
思路: 快速首尾交换,向中间操作
代码实现:

#include<stdio.h>
#include<stdlib.h>

//打印函数:实现对数组元素的打印输出
void print(int Arr[], int len) {
	printf("数组的元素序列为: ");
	for (int i = 0; i < len; i++) {
		printf("%d ", Arr[i]);
	}
	printf("\n");
}
//数组逆序函数:实现对数组元素逆序操作
void reverse(int Arr[], int len) {
	int left = 0;
	int right = len - 1;
	while (left < right) {
		int temp = Arr[left];
		Arr[left] = Arr[right];
		Arr[right] = temp;
		left++;
		right--;
	}
}

int main() {
	int arr2[] = { 1,4,7,8,3,6 };
	int len = sizeof(arr2) / sizeof(arr2[0]);
	printf("逆序前的");
	print(arr2, len);
	reverse(arr2, len);
	printf("逆序后的");
	print(arr2, len);

	system("pause");
	return 0;
}

结果:
在这里插入图片描述

*4.冒泡排序

作用: 做常用的排序算法,对元素内数组进行排序
(1) 实现升序的第一种冒泡排序形式: 每次比较交换,每一轮总是把该轮比较的最大值放在比较的最右边

  • 总是从数组第一位开始往后比较
    在这里插入图片描述
  • 冒泡排序轮数 i :len-1
  • 冒泡排序每轮排序次数 j : len-第 i 轮-1

图解法:
在这里插入图片描述
注意 : 由于数组下标都是从0开始的 故轮数 i 和 比较字数 j 都是从0开始.

代码实现:

#include<stdio.h>
#include<stdlib.h>

//冒泡排序函数:实现对数组升序排列,总是把最大的数放在比较的最右边
void bubbleSort(int str[], int len) {
	for (int i = 0; i < len - 1; i++) {
		for (int j = 0; j < len - i - 1; j++) {
			if (str[j] > str[j + 1]) {
				int temp = str[j];
				str[j] = str[j + 1];
				str[j + 1] = temp;
			}
		}
	}
}
//打印排序后数组的函数
void printS(int str[], int len) {
	printf("数组序列为:");
	for (int i = 0; i < len; i++) {
		printf("%d ", str[i]);
	}
	printf("\n");
}

int main() {
	int s[] = { 2,5,9,7,1,8,3,4 };
	int len = sizeof(s) / sizeof(s[0]);
	printf("升序冒泡排序前的");
	printS(s, len);
	bubbleSort(s,len);
	printf("升序冒泡排序后的");
	printS(s,len);

	system("pause");
	return 0;
}

结果:
在这里插入图片描述
(2) 实现升序的第二种冒泡排序形式: 每次比较交换,每一轮总是把该轮比较的最大值放在比较的最右边

算法描述:

  • 总是从数组最后一位开始往前比较
  • 1 .比较相邻两个数,前者大于后者,则两个数进行交换
  • 2 .每相邻两个数做同样的工作, 执行结束后,找到第一个最小数
  • 3 .重复以上步骤,每次比较范围boune+1(向后移一位),直到升序完成范围,不需要比较

设置初始的比较范围 bound 为[0,size-1], 当前值 数组[current] 初始总是为数组最后一个元素. 换言之就是:下标为current的数组元素两两相邻比较交换,比较的范围总是在数组下标为bound的范围内.

图解法:
在这里插入图片描述
代码实现:

#include<stdio.h>
#include<stdlib.h>

//冒泡排序函数:实现对数组升序排列
void bubbleSort(int str[], int len) {
	int bound = 0;
	for (; bound < len; bound++) {
		for (int cur = len - 1; cur > bound; cur--) {
			if (str[cur - 1] > str[cur]) {
				int temp = str[cur - 1];
				str[cur - 1] = str[cur];
				str[cur] = temp;
			}
		}
	}
}
//打印排序后数组的函数
void printS(int str[], int len) {
	printf("数组序列为:");
	for (int i = 0; i < len; i++) {
		printf("%d ", str[i]);
	}
	printf("\n");
}

int main() {
	int s[] = { 2,5,9,7,1,8,3,4 };
	int len = sizeof(s) / sizeof(s[0]);
	printf("升序冒泡排序前的");
	printS(s, len);
	bubbleSort(s,len);
	printf("升序冒泡排序后的");
	printS(s,len);

	system("pause");
	return 0;
}

结果:
在这里插入图片描述
不同: 两种方法都实现冒泡升序排序,第一种总先找到最大数,第二种总先找到最小数.

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
数组逆序数指的是数组逆序对的数量,即数组中有多少对元素,其索引位置在数组中是逆序的。以下是一个使用C语言计算数组逆序数的示例代码: ```c #include<stdio.h> int merge(int arr[], int temp[], int left, int mid, int right) { int i, j, k; int inv_count = 0; i = left; j = mid; k = left; while ((i <= mid - 1) && (j <= right)) { if (arr[i] <= arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; inv_count += (mid - i); } } while (i <= mid - 1) { temp[k++] = arr[i++]; } while (j <= right) { temp[k++] = arr[j++]; } for (i = left; i <= right; i++) { arr[i] = temp[i]; } return inv_count; } int mergeSort(int arr[], int temp[], int left, int right) { int mid, inv_count = 0; if (right > left) { mid = (right + left) / 2; inv_count = mergeSort(arr, temp, left, mid); inv_count += mergeSort(arr, temp, mid + 1, right); inv_count += merge(arr, temp, left, mid + 1, right); } return inv_count; } int getInvCount(int arr[], int n) { int temp[n]; return mergeSort(arr, temp, 0, n - 1); } int main() { int arr[] = { 1, 20, 6, 4, 5 }; int n = sizeof(arr) / sizeof(arr[0]); printf("逆序数为 %d", getInvCount(arr, n)); return 0; } ``` 运行结果为: ``` 逆序数为 5 ``` 该算法使用了归并排序的思想,在归并排序的过程中计算逆序数。具体来说,将数组分成左右两部分,然后对左右两部分分别进行归并排序,最后将左右两部分合并成一个有序数组,并计算逆序数。逆序数等于左半部分逆序数加右半部分逆序数加左右两部分中的逆序数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值