数组:
大家来想一想
1.什么数组?
2.为什么需要数组?
问题:
int score1;
int score2;
int score3;
int score4;
可以一次性创建多个变量 -- 数组
什么数组:
相同类型的 数据的集合
相同类型的 变量的集合
为什么?
提供了批量处理的方式 -提高了效率
C语言针对数组提供形式
一维数组
二维数组
多维数组
一维数组:
定义的语法:
类型说明符 数组名[常量表达式];
(1) (2) (3)
(1).类型说明符
用来说明 要处理的数据的 类型
(2).数组名
名字 --- 代表这个数组
//更本质的后面说
标识符
起名字规则 变量名命名规则相同
(3).[常量表达式]
[] //表示是个数组
常量表达式 10 10+1
整型常量表达式 //不能是浮点型
表示的是,该数组中有多少个同类型的变量 //数组中的每个变量 --数组的元素
eg:
int score[10]; //表示定义了一个数组,这个数组中有10个元素,每个元素类型是 int型
//表示定义了一个包含了10个int型变量的数组
//数组定义好之后,表示10个int型变量的空间被开辟出来了
int a = 10; //
printf("a = %d\n",a);
一维数组的初始化 和 赋值问题
//初始化方式
//方式1 -- 初始化列表
int score[10] = {1,2,3,4,5,6,7,8,9,10}; //初始化列表 --全部初始化
//方式2 -- 部分初始化
int score[10] = {1,2,3,4,5}; //部分初始化,已初始化部分,挨个给值 未初始化的部分,默认给成0
//全部初始化成 0
int a[10] = {0};
int a[10] = {}; //{} --- 初始化器
//未初始化的数组
随机值(垃圾值)
//数组长度 可以省略,但是前提是,必须要有初始化的值
int a[];// 错误 ---编译器也不知道有多大
int a[] = {1,2,3,4,5}; //编译器会根据给到的元素值的个数来推算出元素的个数(数组长度)
//定义好之后如何给值
//赋值 方式
int a;
a = 10;
int a[10];
//键盘 输入
一维数组元素引用:
需要说明引用的是哪个元素
语法:
数组名[下标]; //[]下标运算
//下标 就是对应元素在数组中的编号
//下标 从0开始
printf("%d\n",score[2]);
int a[10]; //10个int型变量的空间
数组越界:
int a[] = {1,2,3,4,5}; //5个int型变量
注意:
1. 编译器并不检查这种问题
作为程序员 自己小心
2. 数组下标的合法范围
[0~len-1]
3. 下标的本质
数组名:
1.数据类型
数组名 --可以代表数组这种数据类型
sizeof(a) // 整个数组的大小
2.代表值
代表的是数组对应空间的其实地址
数组名所代表的地址为 数组首元素对应的地址
3.数组下标
本质上是相对于首元素的偏移量(偏移了几个元素)
数组特点:
1.连续性 //一片连续的内存空间
2.有序性
3.单一性 //同种类型 内存空间大小都相同
练习1:
定义一个数组, 从键盘输入10个整数,找出数组中能被3整除的数
补充:
注意:
1. c99标准开始,数组长度可以是一个整型变量。
int n ; //变量
int a[n]; //不能初始化
2. 数组 不能 整体操作
只能操作具体的元素
练习:
准备10个整型数,
找出最大值
思路:
打擂台
int max = a[0];
练习:
数组逆序
int a[10] = {1,2,3,4,5,6,7,8,10};
int i = 0;
for (i = 9; i >= 0; --i)
{
printf("%d\n",a[i]);
}
//
int a[10] = { 1,2,3,4,5,6,7,8,9,10};
{10,9,8,7,6,5,4,3,2,1};
0 1 2 3 4 5 6 7 8 9 //下标
{ 1,2,3,4,5,6,7,8,9,10};
{10,9,8,7,6,5,4,3,2,1};
a[i] <=> a[len-1-i]
//对 对应的位置上值交换
循环结束
换到一般
i < len/2
交换两个数:
a[i] a[len-i-1]
int temp = a[i];
a[i] = a[len-i-1];
a[len-i-1] = temp;
i j
0 1 2 3 4 5 6 7 8 9 //下标
{ 1,2,3,4,5,6,7,8,9,10};
{10,9,8,7,6,5,4,3,2,1};
0 9
i j
i++ j--
i < j
-----------------------------------------------
排序:
选择排序
冒泡排序
排序
把数据,从大到小或者从小到大 排列
从大到小 降序
从小到大 升序
选择排序
思想:
给合适位置,选择合适的数
冒泡排序
算法:
理解 抽象
理解 过程
能够 实现代码
算法优化? ---算法的实现
冒泡排序:
思想:
相邻两个元素两两比较 ,小的放前,大的放后
冒泡 和 选择 ,本质上差别不大
判断依据 --- 时间复杂度
for (i = 0; i < len-1; ++i)//控制位置
{
for(j = i+1; j < len; ++j)//找数
{
if (a[j] > a[i])
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
i = 0 j = 1 j < n; //n-1
i = 1 j = 2 j < n; //n-2
...
... //2
i = n-2 j = n-1 j < n; //1
1+2+3+...+n-1 // (1+n-1)(n-1)/2
// n(n-1)/2
// (n^2 - n)/2
O(n^2) //大o记法
//冒泡排序
for (i = len-1; i > 0; --i ) //趟数
{
for (j = 0;j < i; ++j) //一趟过程
{
if (a[j] > a[j+1])
{
int t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
i = n - 1 //n-1
i = n - 2 //n-2
...
i = 1 //1
----------------------------------------------------------------------
总结:
1.数组
概念
2.一维数组
数据类型 数组名[数组长度]
//给值的方式
//初始化
//赋值
//输入
//配合循环
3.引用数组元素
数组名[下标];
1.不要越界
2.浮点类型
int a[10];
a[10]
4.数组特点
连续性
有序性
单一性
//线程
5.练习
1.找最大值
2.逆序
3.选择排序
4.冒泡排序
作业:
1. 从终端输入一个n将数组int a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}
完成如下变化,并打印,操作方式如下:
//n:1 9 1 2 3 4 5 6 7 8
n:2 8 9 1 2 3 4 5 6 7
n:3 7 8 9 1 2 3 4 5 6
n:1 9 1 2 3 4 5 6 7 8
n:-1 2 3 4 5 6 7 8 9 1
数据 的 结构
2. 已知数组a[10]和b[10]中元素的值递增有序,
将两个数组合并为一个数组(有序)并完成打印。
int a[] = {1,3,5,7,9};
int b[] = {2,4,6,8,10};
int c[10+10]
--------------------------------------------------
排序的目的
查找
二分查找 //非常高效的查找方式
思想:
每次找到中间的一个值 进行判断
(二分法)
前提:
数据必须是有序的
-----------------------------------------------
整型二维数组:
背景,
int score[30];
问题:
学习小组
5组
6个同学
int score[6];
二维数组定义:
数据类型 数组名[整型常量表达式][整型常量表达式];
eg:
int score[5][6]; //两维
//理解角度
//表格
//坐标
int score[5][6]; //表示定义了一个5行 6列的一个二维数组
//30个元素
5 个组
6 表示每组 6 个同学
5 行
6 列
int score[30]; //一维
二维数组的初始化:
//全部初始化
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
//按行初始化
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
二维数组元素的引用:
数组名[行下标][列下标];
二维数组的理解:
行列
坐标
二维数组的本质:
满足数组特点
单一性
有序性
连续性
C语言中,并不存在真正的二维数组
int score[4];
int score[3][4]; //
注意:
数组是一种数据类型
int a[4]; // int ---数据类型
// 描述数组中要存放的元素的数据类型
//数组 --的数据类型
//标识符对应的数据类型 --- 标识符去掉,剩下就是其对应的数据类型
int[4] //数组类型 --- 表示是一种包含了4个int型数据的一维数组类型
int[4] a; //int a[4]; //数组
int[4] a[3]; //定义了一个一维数组
//一维数组中的每个元素 又是一个 一维数组类型
//int a[3][4]; //二维数组
int[4] a[3]; //a[0] 就相当于是内部的一维数组(int[4])的数组名
a[0] --->a[0][0] a[0][1] a[0][2] a[0][3]
a[1] --->
a[2] --->
总结:
1.c语言中,并不存在真正的二维数组
2.一维数组的一维数组
3.二维数组 在内存上,数据的存放和一维数组没啥区别
4.二维数组 是按行优先存储
二维数组 --- 一维数组类型的一维数组
--- 数组的数组
二维数组的应用:
矩阵
图片数据
练习:
定义一个二维数组 定义一个 3*3
输入9个数
找出最大值
---------------------------------------------------
字符型数组
字符型一维数组
char ch[10] = {'h','e','l','l','o','w','o','r','l','d'};
多个字符数据 --- 字符串
字符串 --- 一串字符 ---更在乎整体一个意思
字符串:
用来表示 一串字符
"hello" //字符串常量
//字符串在c语言中,都是按字符型一维数组来处理的
//在字符串末尾会默认添加一个结束标志 '\0'
char ch[5] = {'h','e','l','l','o'};
=>'h''e''l''l''o'
"hello" //
=>内存中的形式
'h''e''l''l''o''\0'
字符数组 与 字符串
1.字符数组 可以 用来 存放字符串数据
2.字符串 关心是字符串这个整体
此时结束标志('\0')重要,而数组长度 不那么重要了
编写代码时,数组长度 可能不再需要,而是以结束标志作为判断依据
3.字符数组 和 字符串 写的时候
char str[10] = "hello";
eg:
char str[10] = "hello";
printf("sizeof(str) = %ld\n",sizeof(str));
输出字符串:
puts(); // string
int puts(const char *s);
功能:
输出字符串
参数:
@s 表示存在字符串的空间的首地址
返回值:
非负数 成功
EOF 出错
char *gets(char *s);
功能:
输入字符串
参数:
@s 表示存放字符串的一块空间的首地址
返回值
成功 返回就是s
总结:
字符串的输入输出
gets
//本质 --实际上时字符数组的操作
//最终加了 '\0'
puts
//本质 --实际上就是输出数组中的元素,结束判断条件是'\0'
//gets内部实现
//方式1
do
{
str[i] = getchar();
}while (str[i++] != '\n');//hello\n'\0'
str[i-1] = '\0';
//方式2
while ( (str[i] = getchar()) != '\n')
++i;
str[i] = '\0';
//puts内部实现 --默认自带\n
int i = 0;
while (ch2[i] != '\0')
{
printf("%c",ch2[i]);
++i;
}
putchar('\n');
字符串的输入
gets ()
scanf() //如果输入的字符串中间 有空格 只能接收空格前面的
注意:
空间尽可能足够
否则可能导致越界
字符串函数:
//字符串的长度
"hello" //指的是 '\0'前面字符的个数 --- 字符串长度
strlen();
size_t strlen(const char *s);
功能: 计算字符串长度
参数:
s //存在字符串的一块内存空间的首地址
返回值:
成功 返回 长度
size_t //long int
char str[10] = "hello";
printf("sizeof(str) = %ld\n",sizeof(str)); //数组大小 --- 数组长度
printf("strlen(str) = %ld\n",strlen(str)); //字符串的长度
数组大小 ---数组所占内存空间的字节数
数组长度 ---数组元素个数
字符串长度--- '\0'前字符的个数
#include <string.h> //加头文件
//字符串拷贝
char str1[10] = "hello";
char str2[10];
//str2 = str1;
strcp
char * strcpy(char *dest, const char *src);
功能:
将src中的字符串 拷贝到 dest
参数:
src 存放这源字符串的 一块空间的首地址
dest 存放字符串的目的空间的地址
返回值:
成功 返回dest空间的地址
失败 返回NULL
//字符串拼接
char str1[20] = "hello";
char str2[20] = "world";
strcat
char *strcat(char *dest, const char *src);
功能:
拼接字符串
参数:
dest 拼接的目的字符串对应空间的首地址
src 源字符串对应空间的首地址
返回值
成功 返回dest空间的地址
失败 返回NULL
思路:
1.定位到 目标字符串 '\0'所在位置
2.从 '\0'位置开始,将 源字符串 字符挨个拷贝过来
字符型二维数组