C语言:数组入门及其基础算法详解(๑•̀ㅂ•́)و✧
本篇文章我会用我的理解介绍什么是数组,以及数组的一些基础算法,包含顺序查找,寻找最大值/最小值,数据插入,数据删除,数据倒置,冒泡排序,选择排序,二分查找共八个算法讲解及示例。
一.什么是数组?
本篇文章的重点是算法详解,基本概念简单提一下。
定义
你可以把数组想象成一个有很多个格子的储物柜,其有以下特性:
- 同一数据类型: 储物柜每个格子都只能存放同种类型 的物品(比如全是书或者全是衣服),在编程中,即元素均为同种数据类型(全是整型int或全是字符型char)
- 连续内存空间: 这些格子是一个接一个,连续排列的
- 下标(索引)访问: 每个格子都有一个编号,我们称作下标或索引,且编号从0开始
表示
基本格式:
- 数组数据类型 数组名称[元素个数];
- 数组数据类型 数组名称[(元素个数)]={元素1,元素2...元素n};
第二种形式下的元素个数可不写,系统会自动计算后面{}中的元素个数,若填写,此形式下的"元素个数"应≥n
eg:int num[5] ={1,2,3,4,5}; 其中,num[0] = 1;num[3] = 4;
常用基础算法(。•̀ᴗ-)✧
以下算法全部基于 int num[5] = {1,2,3,4,5};进行
1.顺序查找
就像在一排房子里找人,从第一家开始问
eg : 查找数组 num 中值为 4 的元素及其位置
c
#include <stdio.h>
int main() {
int num[5] = {1,2,3,4,5};
int n = 4;//要找的元素
int found = 0;//0表示没找到,1表示找到了,先假设没找到
int i;
//从第一个开始逐个寻找(也称遍历数组)
for(i = 0;i < 5;i++){
if(num[i]==n){ //如果第i位数字等于n,代表找到
found = 1;
break;//找到就停止循环
}
}
if(found==1){
printf("找到了!%d在数组第%d位",n,i+1); //注意:数组从0开始计数,因此此处为i+1
}
else{
printf("没找到!");
}
return 0;
}
//输出
//找到了!4在数组第4位
2.寻找最大值/最小值
就像选班长,先定下一个人,再跟其他人进行比较
eg : 寻找并输出数组 num 中的最大值
c
#include <stdio.h>
int main() {
int num[5] = {1,2,3,4,5};
int n = 4;
int max = num[0];//先假设最大值为num[0],即1
int i;
//遍历数组
for(i = 1;i < 5;i++){//此处i从1开始,因为num[0]已经被假设为最大值,不需要再和自己比较一次
if(num[i]>max){
max = num[i];//找到更大的就更新
}
}
printf("最大值为%d",max);
return 0;
}
//输出
//最大值为5
3.数据插入
就像排队插队,后面的人都要往后挪一位
eg :先输出插入前的数组 num ,再在数组 num 中第2位和第3位数字中间插入一个数字10并输出插入后的新数组
c
#include <stdio.h>
int main() {
int num[6] = {1,2,3,4,5};
int n = 10;//要插入的数字
int position = 2;//要插入的位置(第3位)(数组从0开始计数,因此此处是2)
//打印插入前数组
for(int i = 0;i < 5;i++){
printf("%d ",num[i]);
}
printf("\n");
//开始插入操作
//从后往前,将插入位置及其之后的元素往后移一位
for(int i = 4;i>=position;i--){
//思考此处i为什么不能等于5?因为此时数组计数范围为0~5共6个数字,若i=5,在执行下行操作时,会变成num[6]=num[5],num[6]超过计数范围(也称越界),程序错误
num[i+1] = num[i];
}
//插入新值n
num[position] = n;
//打印插入后的新数组
for(int i = 0;i < 6;i++){
printf("%d ",num[i]);
}
return 0;
}
//输出
//1 2 3 4 5
//1 2 10 3 4 5
4.数据删除
就像有人离开队伍,后面的人往前补上
eg : 先输删除前的数组,再将数组中值为3的元素删除并输出删除后的新数组
c
#include <stdio.h>
int main() {
int num[5] = {1,2,3,4,5};
int position = 2;//要删除的位置(第三位)
//打印删除前的数组
for(int i = 0;i < 5;i++){
printf("%d ",num[i]);
}
printf("\n");
//开始删除操作
//从前往后,将删除位置之后的位置往前进一位
for(int i = position+1;i<5;i++){//注意这里删除位置不参与循环,所以i=position+1
num[i-1] = num[i];
}
//打印删除后的数组
for(int i = 0;i < 4;i++){
printf("%d ",num[i]);
}
return 0;
}
//输出
//1 2 3 4 5
//1 2 4 5
5.数据倒置
就像把一本书倒过来读
eg : 先将原数组打印,再将数组 num 按相反顺序打印
c
#include <stdio.h>
int main() {
int num[5] = {1,2,3,4,5};
//打印原数组
for(int i = 0;i < 5;i++){
printf("%d ",num[i]);
}
printf("\n");
//开始倒置操作
//交换第一个和最后一个,交换第二个和倒数第二个
for(int i = 0;i<2;i++){//只需要执行 交换前一半 的操作,因此i<2
int temp = num[i];
num[i] = num[4-i];
num[4-i] = temp;
}
//打印倒置后的数组
for(int i = 0;i < 5;i++){
printf("%d ",num[i]);
}
return 0;
}
//输出
//1 2 3 4 5
//5 4 3 2 1
如果觉得这种方法不好理解,也可以使用另一种(也是我比较喜欢用的一种):定义一个新的空数组,将数组 num 从后往前遍历,并依次从前往后填入新数组,新数组即为倒置后的数组num.(可以尝试一下,这里就不写出来了,我觉得很好理解(~ ̄▽ ̄)~
6.冒泡排序(每轮排出最大的数)
就像水中的气泡,大的往上冒(虽然这么取名,但从小到大排列和从大到小排列均可用此方法)
这个算法我认为直接看代码和注释很抽象,很难理解,建议先上网搜索"冒泡排序算法动画演示"先看视频理解一下,我觉得帮助很大(=`ω´=)
eg : 先将数组 int num[5] = {2,5,4,1,3}; 打印,再将其内元素按从小到大的顺序输出
c
#include <stdio.h>
int main() {
int num[5] = {2,5,4,1,3};
//打印原数组
for(int i = 0;i < 5;i++){
printf("%d ",num[i]);
}
printf("\n");
//开始冒泡排序
for(int i = 0;i<4;i++){ //需要比较4轮,即(数组元素个数-1)轮
for(int j = 0;j<4-i;j++){ //每轮比较次数减小
if(num[j]>num[j+1]){ //如果前面的比后面的大
//交换两个数
int temp = num[j+1];
num[j+1] = num[j];
num[j] = temp;
}
}
}
//打印排序后的数组
for(int i = 0;i < 5;i++){
printf("%d ",num[i]);
}
return 0;
}
//输出
//2 5 4 1 3
//1 2 3 4 5
7.简单选择排序(每轮排出最小的数)
就像选最小的苹果放到最前面(同6.此方法可用于从小到大和从大到小排序)
和冒泡排序一样,建议配合网上的执行动画一起看( ˙꒳˙ )
eg : 先将数组 int num[5] = {2,5,4,1,3}; 打印,再将其内元素按从小到大的顺序输出
c
#include <stdio.h>
int main() {
int num[5] = {2,5,4,1,3};
//打印原数组
for(int i = 0;i < 5;i++){
printf("%d ",num[i]);
}
printf("\n");
//开始选择排序
for(int i = 0;i<4;i++){ //需要选择4次,即(数组元素个数-1)次
int min = i;//假设最小的数是数组第i位元素
//在剩下的里面找真正的最小值
for(int j = i+1;j<5;j++){
if(num[j]<num[min]){ //依次比较,找出最小值
min = j;
}
}
//若假设的最小值不是真正的最小值,则将这两个元素互换位置
if(min != i){
int temp = num[i];
num[i] = num[min];
num[min] = temp;
}
}
//打印排序后的数组
for(int i = 0;i < 5;i++){
printf("%d ",num[i]);
}
return 0;
}
//输出
//2 5 4 1 3
//1 2 3 4 5
8.二分查找(!!!要求数组必须是有序的)
就像猜数字游戏,每次都猜中间值
eg : 查找 num 数列中值为30的元素并打印其位置
c
#include <stdio.h>
int main() {
int num[5] = {1,2,3,4,5};
int n = 3; //要找的数
int left = 0; //左边起点
int right = 4; //右边起点
int found = 0; //是否找到
while(left<=right){
int mid = (left+right)/2; //中间位置
printf("在%d到%d之间查找,中间是%d\n",left,right,mid);
if(num[mid]==n){
printf("找到了!在第%d个位置(下标%d)\n",mid+1,mid);
found = 1;
break;//找到输出,并停止循环
}
else if(num[mid]<n){ //中间的数小于要找的数
left = mid+1; //在右半边找
}
else{ //中间的数大于要找的数
right = mid-1; //在左半边找
}
}
if(!found){
printf("没找到");
}
return 0;
}
//输出
//在0到4之间查找,中间是2
//找到了!在第3个位置(下标2)