数组的定义
练习
#include <stdio.h>
int main() {
/*
数组的定义格式:
数据类型 数组名[长度]
*/
//1.定义数组存储全班8e位同学的年龄
int arr1[80];
//2.定义数组存储全班5@位同学的身高
double arr2[50];
//3.定义数组存储全身每件衣服的价格
double arr3[3];
return 0;
}
数组的初始化
练习
#include <stdio.h>
int main() {
/*
数组的定义并初始化的格式:
数据类型 数组名[长度] = {数据1,数据2...};
细节1:
如果数组的长度没有写,数据值的个数就是数组的长度
细节2:
如果数组的长度已经写上,数据值的个数 <= 长度
未赋值的部分有默认值
整数:0
小数:0.0
字符:"\0'
字符串:NULL(什么都没有)
*/
//1.定义数组存储5个学生的年龄,并初始化。
int arr1[5] = {17,18,19,20,21};
int arr2[] = {17,18,19,20,21};
//2.定义数组存储你女朋友的身高,并初始化。
double arr3[2] = {1.68,1.53};
double arr4[] = {1.68,1.53};
//如果我的两个女朋友的身高,我都不知道
double arr5[2] = {0.0};
return 0;
}
元素访问
索引
练习
#include <stdio.h>
int main() {
/*
需求:
定义一个长度为5的数组,并进行初始化:1 2 3 4 5
完成下列要求:
1.获取索引为0,2,4的元素,并求和
2.把最后一个索引上的元素修改为10
*/
// 1.定义一个长度为5的数组,并进行初始化:1 2 3 4 5
int arr[] = {1,2,3,4,5};
// 2.获取索引为0,2,4的元素,并求和
int num1 = arr[0];
int num2 = arr[2];
int num3 = arr[4];
int sum = num1 + num2 + num3;
printf("%d\n",sum);//9
// 3.把最后一个索引上的元素修改为10
//索引的范围:最小索引 0
// 最大索引 长度 - 1
printf("%d\n", arr[4]);//5
arr[4] = 10;
printf("%d\n", arr[4]);//10
return 0;
}
数组遍历
练习
#include <stdio.h>
int main() {
/*
需求:
定义一个长度为5的数组,并进行初始化:1 2 3 4 5
完成下列要求:
遍历数组,并把每一个元素打印到控制台
*/
// 1.定义一个长度为5的数组,并进行初始化:1 2 3 4 5
int arr[] = {1,2,3,4,5};
// 2.获取
//利用循环遍历数组
for (int i = 0; i < 5; i++) {
//i:依次表示数组里面的每一个素引
printf("%d\n", arr[i]);
}
return 0;
}
内存中的变量、数组
内存
内存地址
内存中的变量
#include <stdio.h>
int main() {
// 获取变量的内存地址
int a = 10;
printf("%p\n", &a); //0000006E05DAF594 十六进制
return 0;
}
内存中的数组
#include <stdio.h>
int main() {
// 获取数组的内存地址
int arr[] = {1,2,3};
printf("%p\n", &arr); //0000003B598FF8E8 数组的首地址(第一个元素,第一个格子的内存地址)
printf("%p\n", &arr[0]); //0000003B598FF8E8 第一个元素内存地址
// 索引:从内存的角度看 -> 偏移量(首地址 + 往后进行偏移)
printf("%p\n", &arr[1]); //0000003B598FF8EC 偏移4个字节
return 0;
}
总结
思考
在底层实现上,计算机内存是线性的,每个内存单元都有一个唯一的地址。通过从0开始索引数组,可以通过简单的偏移量计算来访问数组的元素,因为数组的第一个元素的地址就是数组本身的地址加上0。
数组的常见问题
#include <stdio.h>
void printArr(int arr[],int len);
int main() {
/*
1.数组作为函数的参数,要注意什么?
实际上传递是数组的首地址,如果要在函数中对数组进行遍历的话,记得一定要把数组的长度一起传递过去
定义处:arr表示的就是完整的数组
函数中的arr:只是一个变量,用来记录数组的首地址
2.数组的索引越界
最小系引:8
最大索引:长度 -1
*/
// 1.定义数组
int arr[] = { 1,2,3,4,5 };
//printf("%zu\n", sizeof(arr)); //20
int len = sizeof(arr) / sizeof(int); //20
//printf("%d ", arr[10]);索引越界
// 2.调用函数遍历数组
printArr(arr,len);
return 0;
}
void printArr(int arr[],int len){
//64位的操作系统当中,是以64个二进制表示内存地址值
//printf("%zu\n", sizeof(arr)); //8
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
}
数组的算法题
求最值
#include <stdio.h>
int main() {
/*
思考一:
循环是不是一定要从0索引开始?
不是的,如果max的默认值记录的是e索引的,循环就可以从1开始,提高效率
思考二:
max的默认值是否可以写为0?
不可以的,如果数组里面所有的数据都是负数,循环结束之后,得到的最大值0,此时会给别人产生误解
max的默认值:一定要是数组中已经存在的数据,一般都是把0家引当做默认值
*/
// 1.定义数组
int arr[] = {33,5 ,22,44,55};
// 2.定义变量max,记录数组的最大值
int max= arr[0];
// 3.遍历数组得到每一个元素,拿着遍历到的元素跟max进行比较
// 遍历到的元素 <= max里面记录的数据 不做任何处理
// 遍历到的元素 > max里面记录的数据 max就要修改成新的值
int len= sizeof(arr)/sizeof(int);
for (int i = 0; i < len; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 4.输出max
printf("%d\n", max);//55
return 0;
}
求和
基础版
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
// 1.定义数组
int arr[10] = { 0 };
int len = sizeof(arr) / sizeof(0);
// 2.生成10个1~100之间的随机数存入数组
// 设置种子
srand(time(NULL));
// 生成随机数
for (int i = 0; i < len; i++) {
int num = rand() % 100 + 1;
// 把随机数存入到数组
arr[i] = num;
}
// 3.利用累加思想求数组中所有数据的和
int sum = 0;
for (int i = 0; i < len; i++) {
sum += arr[i];
}
//输出
printf("%d\n", sum);
return 0;
}
升级版
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int contains(int arr[], int len, int num);
int main() {
// 1.定义数组
int arr[10] = { 0 };
int len = sizeof(arr) / sizeof(0);
// 2.生成10个1~100之间的随机数存入数组
// 设置种子
srand(time(NULL));
// 生成随机数
for (int i = 0; i < len;) {
int num = rand() % 100 + 1;
//存入之前,先做一个判断,如果不存在,再进行添加
int flag=contains(arr,len, num);
if (!flag) {
arr[i] = num;
i++;
}
}
for (int i = 0; i < len; i++) {
printf("%d ",arr[i]);
}
printf("\n");
// 3.利用累加思想求数组中所有数据的和
int sum = 0;
for (int i = 0; i < len; i++) {
sum += arr[i];
}
// 4. 求平均数
int avg = sum / len;
// 5.统计有多少个数字比平均数小
int count = 0;
for (int i = 0; i < len; i++) {
if (arr[i] < avg) {
count++;
}
}
// 6.输出
printf("和为:%d\n", sum);
printf("平均数为:%d\n", avg);
printf("%d\n", count);
return 0;
}
// 判断num在函数当中,是否存在
// 存在,返回1
// 不存在,返回0
int contains(int arr[],int len,int num) {
for (int i = 0; i < len; i++) {
// i:依次表示数组里面的每一个案引
// arr[i]:依次表示数组里面的每一个数据
if (arr[i] == num) {
return 1;
}
}
return 0;
}
反转数组
#include <stdio.h>
void printArr(int arr[], int len);
int main() {
// 1.定义数组
int arr[5] = { 0 };
int len = sizeof(arr) / sizeof(0);
// 2.键盘录入数据
for (int i = 0; i < len; i++) {
printf("请录入第%d个元素\n",i + 1);
scanf("%d", &arr[i]);
}
// 3.遍历数组
printArr(arr, len);
// 4.反转数组
int i = 0;
int j = len - 1;
while (i < j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
// 5.遍历数组
printArr(arr, len);
return 0;
}
void printArr(int arr[], int len) {
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
打乱数据
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
// 1.定义数组
int arr[] = { 1,2,3,4,5 };
int len = sizeof(arr) / sizeof(int);
// 2.遍历数组,得到每一个元素,让这个元素跟随机索引处的元素进行交换
// 设置种子
srand(time(NULL));
for (int i = 0; i < len; i++) {
//获取一个随机索引
// 0 ~ 4
int index = rand() % len;
// 拿着i指向的元素,跟index指向的元素进行交换
int temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
// 3.遍历数组
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
return 0;
}
}
常见算法
查找算法
基本查找/顺序查找
#include <stdio.h>
int order(int arr[], int len, int num);
int main() {
/*
需求:数组的基本查找/顺序查找
核心思路:就是从数组的8索引开始,依次往后查找
如果找到了,就会返回数据对应的索引
如果没有找到,就会返回-1
*/
// 1.定义数组
int arr[] = { 11,22,55,77,44 };
int len = sizeof(arr) / sizeof(int);
// 2.定义一个变量表示要查找的数据
int num = 55;
// 3.调用函数查找数据
int index = order(arr,len, num);
// 4.输出索引
printf("%d\n", index);
return 0;
}
//作用:查找数组中的数据//返回值:数据所在的索引
int order(int arr[], int len, int num) {
for (int i = 0; i < len; i++)
if (arr[i] == num) {
return i;
}
return -1;
}
二分查找/折半查找
#include <stdio.h>
int binarysearch(int arr[], int len, int num);
int main() {
/*
需求:数组的二分查找
在7,23,79,81,103,127,131,147中查找数据
*/
// 1.定义数组
int arr[] = { 7,23,79,81,103,127,131,147 };
int len = sizeof(arr) / sizeof(int);
// 2.定义变量表示要查找的数据
int num = 131;
// 3.调用函数查找数据
int index = binarysearch(arr, len, num);
// 4.输出
printf("%d\n", index);
}
// 作用:利用二分查找法查找数据
// 返回值:数据在数组中的索引
// 找到了,真实的索引
// 没有找到,返回 -1
int binarysearch(int arr[], int len, int num) {
// 1.确定查找的范围
int min = 0;
int max = len - 1;
//2.利用循环不断地进行查找
while (min <= max) {
// 确定中间位置
int mid = (min + max) / 2;
// 比较
// min max mid 表示案引
// num 表示要查找的元素
// 坑:arr[mid]跟num 进行比较
if (arr[mid] < num) {
// 要查找的数据是在右边
min = mid + 1;
}
else if (arr[mid] > num) {
//要查找的数据是在左边
max = mid - 1;
}
else {
return mid;
}
}
return -1;
}
总结
插值查找(二分查找改进)
总结
分块查找
排序算法
冒泡排序
#include <stdio.h>
int main() {
/*
需求:
利用冒泡排序将下列数据按照从小到大的顺序进行排序
3,5,2,1,4
*/
// 1.定义数组存储数据
int arr[] = { 3,5,2,1,4 };
int len = sizeof(arr) / sizeof(int);
// 2.利用冒泡排序,把数组中的数据按照升序排列
// 双重循环本质:就是把内循环重复执行了N次而已
// 首先看内循环的作用
//
// 内循环:找到本次循环的较大值,再把较大值放到了最右边
// 外循环:把上面的这个动作重复执行了4次
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - 1 - i; j++) {
//相邻的元素两两比较,小的在前面,大的后面
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
return 0;
}
选择排序
#include <stdio.h>
int main() {
/*
需求:
利用冒泡排序将下列数据按照从小到大的顺序进行排序
3,5,2,1,4
*/
// 1.定义数组存储元素
int arr[] = { 3,5,2,1,4 };
int len = sizeof(arr) / sizeof(int);
// 2.利用选择排序,把数组中的数据按照升序排列
for (int i = 0; i < len - 1; i++) {
//i:依次表示数组中的每一个索引
// 第一轮:i = 8 j = 1 2 3 4
// 第二轮:i = 1 j = 2 3 4
// 第三轮:i = 2 j = 3 4
// 第四轮:i = 3 j = 4
for (int j = i + 1; j < len; j++) {
//相邻的元素两两比较,小的在前面,大的后面
if (arr[i] > arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
// 遍历
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
return 0;
}