一.数组:
1. 基本含义
- 变量:
- 内存中的一块空间
- 数组内存中的一串连续的空间
- 数组:是一个变量,由数据类型相同的一组元素组成
2. 数组的结构和基本要素
- 标识符:数组的名称,用于区分不同的数组
- 数组元素:向数组中存放的数据
- 元素下标:对数组元素进行编写
- 元素类型:数组元素的数据类型
3.语法
-
声明:
datetype arrayNames[size]; int nums[5] = {1, 2, 3, 4, 5};
4.程序示例
- demon1
#include <stdio.h>
#define N 5 //宏定义
int main()
{
double score[5];
int i; //循环变量
//使用循环操作数组时,要注意:一个循环尽量只做一件事
for(i = 0; i < N; i++)
{
printf("请输入第%d位同学的成绩:", i + 1);
scanf("%lf", &score[i]);
}
//下面的循环用来打印数组元素
for(i = 0; i < N; i++)
{
printf("第%d位同学的成绩是:%.2lf\n", i + 1, score[i]);
}
return 0;
}
- demon2
#include <stdio.h>
int main()
{
int i;
int sum = 0;
double avg; //求平均
int searchNum; //要查找的数字
//1.定义数组并初始化
int nums[] = {8, 4, 2, 1, 23, 344, 12};
//2.循环输出
printf("输出数组元素:\n");
for(i = 0; i < 7; i++)
{
printf("%d\t", nums[i]);
}
printf("\n******************************\n");
//3.求和、求平均值
for(i = 0; i < 7; i++)
{
sum += nums[i]; //经典累加
}
avg = sum / 7.0;
printf("平均值是:%.2lf\n", avg);
//4.查找数字
printf("请输入要查找的数字:");
scanf("%d", &searchNum);
for(i= 0; i < 7; i++)
{
if(searchNum == nums[i]) //一个一个元素对比
{
printf("找到了!\n");
break;
}
}
if(i == 7)
printf("茫茫人海,你在哪里!\n");
return 0;
}
二.冒泡排序:
1. 降序排列
- 冒泡排序的基础原理:遍历和交换
- 排序
- 每轮轮循环:当前数字小于后面的数字,则进行交换
- 第一轮比较次数 = 数组长度 - 1
- 需要多轮循环,每一轮循环比较次数比上一轮减1次
demon
#include <stdio.h>
#define N 5 //宏定义
int main()
{
//冒泡排序
int i, j; //循环变量
int nums[N] = {16, 25, 9, 90, 23};
int temp; //用来交换的临时变量
//外层循环控制轮数
for(i = 0; i < N - 1;i++ )
{
//内层循环控制每轮的比较次数
for(j = 0; j < N - i - 1;j++)
{
//如果当前值小于后面就交换
if(nums[j] < nums[j + 1])
{
temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
printf("排序后的结果是:\n");
for(i = 0; i < N; i++)
{
printf("%d\t", nums[i]);
}
return 0;
}
2. 逆序排列
-
数组有序:
逆序采用冒泡排序的方式
-
数组无序:
1.第一个元素与最后一个交换 2.第二个元素与倒数第二个交换 3.归纳可知第 i 个元素与第(N - i - 1)个元素交换 4.数组元素偶数个逆序进行N/2次交换,奇数个进行(N - 1)/2次交换
demon
#include <stdio.h>
#define N 5
int main()
{
//逆序排列
int i; //循环变量
int temp; //临时变量
int nums[N] = {12, 34, 23, 67, 9};
for(i = 0; i < N / 2 ; i++) //进行N/2次即逆序排列,若是N次互换将会还原
{
temp = nums[i];
nums[i] = nums[N - i -1];
nums[N - i - 1] = temp;
}
printf("输出排序后的数组元素:\n");
for(i = 0; i < N; i++)
{
printf("%d\t", nums[i]);
}
return 0;
}
3. 数组元素的删除和插入
-
删除的逻辑
1.查找删除数字的下标 2.从下标开始,后面一个覆盖前面一个数字 3.数组总长度 - 1
-
添加元素:
在数组预留空间足够的情况下,添加数值即可
demon
#include <stdio.h>
int main()
{
//根据要求操作排行榜战力值
int i, j; //定义循环变量
double temp; //定义临时变量
int count = 5;
double powers[] = {41000, 42000, 43000, 44000,45000};
double deletePower; //用户要删除的战力值
int deleteIndex = -1; //要删除战力值的下标,给一个不可能的值
double insertPowers;
//排序
for(i = 0; i < count -1; i++)
{
for(j = 0; j < count - i - 1; j++)
{
if(powers[j] < powers[j + 1])
{
temp = powers[j];
powers[j] = powers[j + 1];
powers[j + 1] = temp;
}
}
}
printf("战力值从大到小排列为:");
for(i = 0; i < count; i++)
{
printf("%lf\t", powers[i]);
}
//删除某个战力值
printf("\n请输入要删除的战力值:");
scanf("%lf", &deletePower);
for(i = 0; i < count; i++)
{
if(deletePower == powers[i])
{
//记录下当前的下标
deleteIndex = i;
break;
}
}
if(-1 == deleteIndex) //判断是否找到
{
printf("很遗憾,没有找到要删除的战力值,删除失败!\n");
}
else
{
//从下标开始,后面一个覆盖前面一个数字
for(i = deleteIndex; i < count - 1; i++)
{
powers[i] = powers[i + 1];
}
count--; //删除完毕后,一定记得数组的总长度-1 障眼法要做到底
}
printf("删除后的结果为:");
for(i = 0; i < count; i++)
{
printf("%lf\t", powers[i]);
}
//插入一个战力值,并按降序排列
printf("\n输入想要插入的战力值:");
scanf("%lf", &insertPowers);
powers[count] = insertPowers; //插入元素
count++;
printf("插入后的元素:");
for(i = 0; i < count; i++)
{
printf("%lf\t", powers[i]);
}
for(i = 0; i < count; i++) //升序排列
{
for(j = 0; j < count -i -1; j++)
{
if(powers[j] > powers[j + 1])
{
temp = powers[j];
powers[j] = powers[j + 1];
powers[j + 1] = temp;
}
}
}
printf("\n升序排列为:");
for(i = 0; i < count; i++)
{
printf("%lf\t", powers[i]);
}
return 0;
}
4. 二维数组
-
二维数组
声明:datatype names[size_row][size_column];
demon1
#include <stdio.h>
#define ROW 3
#define COL 3
int main()
{
//使用二维数组表示4个学生3门成绩表
double scores[ROW][COL];
int i, j; //定义循环变量
for(i = 0; i < ROW; i++)
{
for(j = 0; j < COL; j++)
{
printf("第%d位同学的第%d门课成绩:", i + 1, j + 1);
scanf("%lf", &scores[i][j]);
}
}
//打印成绩
for(i = 0; i < ROW; i++)
{
for(j = 0; j < COL; j++)
{
printf("%.2lf\t", scores[i][j]);
}
printf("\n");
}
return 0;
}
demon2
#include <stdio.h>
#define R 4
#define C 3
int main()
{
int i, j; //定义循环变量
double scores[R][C]; //定义一个4行3列的数组
//= {{80, 85, 90}, {81, 86, 92}, {82,91,90}, {79, 88, 80}}
//录入成绩
printf("科目\t语文\t英语\t数学\n");
for(i = 0; i < R; i++)
{
printf("学生%d\t", i + 1);
for(j = 0; j < C; j++)
{
scanf("%8lf", &scores[i][j]);
printf("\t");
}
printf("\n");
}
//打印成绩
printf("科目\t语文\t英语\t数学\n");
for(i = 0; i < R; i++)
{
printf("学生%d\t", i + 1);
for(j = 0; j < C; j++)
{
printf("%-4.2lf\t", scores[i][j]); //负号左对齐
}
printf("\n");
}
return 0;
}
快速排序的基本思路:
1.从需要排序的数据中,找到一个适当的基准值(pivot)
2.将需要排序的数据按照小于pivot和大于pivot进行分类
3.对分类后的两类数据各自进行上述的1和2的处理
第二部分类:
1. 从左向右,检索比pivot大的数据
2. 从右向左,检索比pivot小的数据
3. 如果两个方向都能搜索到数据,将找到的数据交换
4. 重复进行1-3的操作,直到从左开始检索的下标和从右开始检索的下标冲突为止
快速排序代码:
#define SWAP(a, b) {int temp; temp = a; a= b; b = temp;};
void quick_sort_sub(int *data, int left, int right)
{
int left_index = left;
int right_index = right;
int pivot = data[(left + right)/2];
while(left_index <= right_index)
{
for(; data[left_index] < pivot; left_index++)
;
for(; data[right_index] < pivot; right_index--)
;
if(left_index <= right_index)
{
SWAP(data[left_index], data[right_index]);
left_index++;
right_index--;
}
}
if(right_index > left)
{
quick_sort_sub(data,left, right_index);
}
if(left_index < right)
{
quick_sort_sub(data, left_index, right);
}
}
void quick_sort(int *data, int data_size)
{
quick_sort_sub(data,0, data_size - 1);
}
注解:
1.这个程序将数组分成两部分之后,再进行递归调用。
2.此时,**在栈中分配了新的用于当前部分数组的内存区域**。
3.另外,当某部分数组的数据处理完毕,函数调用返回的时候,栈会收缩,调用前的状态恰好处于栈的最初位置。
4.正因为如此,处理才这样不断地向右移动。