数组
| 这个作业属于哪个班级 | C语言--网络2011/2012 |
| ---- | ---- | ---- |
| 这个作业的地址 | C博客作业04--数组 |
| 这个作业的目标 | 学习数组相关内容 |
| 姓名 | 吕以晴 |
0.展示PTA总分(0----2)
1.本章学习总结(3分)
1.1 学习内容总结
⭐数组中如何查找数据
有序数组
- 二分法
采用二分法,将最中间的数与用户输入的数进行比较,逐步缩小所求数在数组中的区间(+1或-1),直至匹配,或得出无法找到的结论。
无序数组
无序数组没有规律,它的查找只能线性进行,通过循环将数组中的前后元素逐个比较。
#include <stdio.h>
#define MAX 20
int main()
{
int n;//输入n个整数
int x;//需要找到的数字
int arr[MAX];//定义数组用于储存输入的整数
int flag = 1;
scanf("%d %d", &n,&x);
for (int i = 0; i < n; i++)//输入数组的各个元素
{
scanf("%d", &arr[i]);
}
for (int i = 0; i < n; i++)//遍历数组,寻找数字x
{
if (arr[i] == x)//找到所需数字
{
printf("%d", i);
flag = 0;
break;
}
}
if (flag)//遍历数组后仍未寻到所需数字
{
printf("Not Found");
}
return 0;
}
⭐数组中如何插入数据
输入一个数x,将数组中的元素与x逐一比较,如果其大于x,则记录该元素的下标i,然后此元素下标和其后的元素的下标都加一,即后移一位,然后将x赋值给数组的那个下标arr[i]。
#include <stdio.h>
#define MAX 10
int main()
{
int n,x;
int temp;
int arr[MAX];
//输入
scanf("%d", &n);//输入个数
for (int i = 0; i < n; i++)//循环输入数组元素
{
scanf("%d", &arr[i]);
}
scanf("%d", &x);//输入需插入的数
//插入排序
if (x >= arr[n - 1])//插在尾
{
arr[n] = x;
}
else if (x <= arr[0])//插在头
{
for (int i = n; i > 0; i--)
{
arr[i] = arr[i - 1];
}
arr[0] = x;
}
else//插在中间
{
for (int i = 0; i < n; i++)
{
if ((arr[i] <= x && arr[i + 1] > x) || x <= arr[i])
{
for (int j = n; j > i + 1; j--)
{
arr[j] = arr[j - 1];
}
arr[i + 1] = x;
break;
}
}
}
//输出数组元素
int flag = 1;
for (int i = 0; i <= n; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
⭐数组中如何删除数据
输入一个数x,将数组中的元素与x逐一比较,若某一数组元素等于x,则记录该元素的下标i,且其后的数据都向前移位,实现覆盖第i项数据。
#include <stdio.h>
#define MAX 100
int main()
{
int n;//表示数组元素个数
int arr[MAX];
int k;//表示删除次数
int x;//表示每行删掉的数
int num;
//输入
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
scanf("%d", &k);
//删除元素
num = n;//数组元素个数
for (int i = 1; i <= k; i++)//删除次数
{
scanf("%d", &x);
for (int i = x - 1; i < num - 1; i++)
{
arr[i] = arr[i + 1];
}
num -= 1;
}
//输出
for (int i = 0; i < n - k; i++)
{
if (i == 0)//第一次输出,前不带空格
printf("%d", arr[i]);
else
printf(" %d", arr[i]);
}
return 0;
}
⭐数组中目前学到排序方法及主要思路
- 冒泡法
从当前元素起,向后依次比较每一对相邻元素,若逆序则交换。对所有元素均重复以上步骤,直至最后一个元素。
上方gif动图来自网络,某大佬博主
#include <stdio.h>
#define MAX 255 /*数组长度上限*/
void bubbleSort (int arr[], int len)
{
int temp;
int i, j;
for (i=0; i<len-1; i++) /* 外循环为排序趟数,len个数进行len-1趟 */
for (j=0; j<len-1-i; j++) { /* 内循环为每趟比较的次数,第i趟比较len-i次 */
if (arr[j] > arr[j+1]) { /* 相邻元素比较,若逆序则交换(升序为左大于右,降序反之) */
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
int main (void) {
int arr[ARR_LEN] = {3,5,1,-7,4,9,-6,8,10,4};
int len = 10;
int i;
bubbleSort (arr, len);
for (i=0; i<len; i++)
printf ("%d\t", arr[i]);
printf("\n");
return 0;
}
- 选择法
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。
上方gif动图来自网络,某大佬博主
#include <stdio.h>
void swap(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void selectionSort(int arr[], int len)
{
int i,j;
for (i = 0 ; i < len - 1 ; i++)
{
int min = i;
for (j = i + 1; j < len; j++)
if (arr[j] < arr[min])
min = j;
swap(&arr[min], &arr[i]);
}
}
冒泡法与选择法的区别
- 冒泡算法,每次比较如果发现较小的元素在后面,就交换两个相邻的元素。
- 而选择排序算法先并不急于调换位置,先从a[0]开始逐个检查,看哪个数最小就记下该数的下标i,等一次遍历后,再把a[i]和a[0]对调,这时a[0]到a[10]中最小的数据就换到了最前面的位置。
- 即选择排序每扫描一遍数组,只需要一次交换,而冒泡可能需要很多次。
⭐数组做枚举用法
用0-N的整形数字做下标可读性不高,为解决这个问题,我们可以使用枚举变量作为下标来访问数组。
enum color{black,white,red,blue,green}; //类型定义
enum color{black,white,red,blue,green} color1; //定义变量
enum color{black,white,red,blue,green} colorx[2]; //定义枚举类型的数组变量
- enum 是枚举,也就说如果变量的类型为enum, 那么它的取值只可以是这个枚举中的一种。
⭐哈希数组用法
将一大类数据用已知的hash函数进行分类,映射到固定大小的数组中。
#include<stdio.h>//此处参考借用了网络上的哈希查找案例
#define LEN 13
#define N 11
int data[N]={10,9,8,7,5,4,6,3,2,1,95}; //原始数据;
int hash[LEN]={0}; //哈希表,初始化为0;
void Create()
{
for(int i=0;i<N;i++) //循环将原始数据保存到哈希表中;
{
//将关键字插入到哈希表hash中;
int j=data[i]%13; //计算哈希地址;
while(hash[j]) //元素位置已被占用;
j=(++j)%LEN; //线性探测法解决冲突;
hash[j]=data[i];
}
}
int Haxi_Sou(int key)
{
int i=key%LEN; //计算哈希地址;
while(hash[i]&&hash[i]!=key) //判断是否冲突;
i=(++i)%LEN; //线性探测法解决冲突;
if(hash[i]==0) //查找到开放单元,表示查找失败;
return -1; //返回失败值;
else
return i; //返回对应的元素下标;
}
int main(void)
{
int key;
Create(); //调用函数创建哈希表;
printf("哈希表中各元素的值:");
for(int i=0;i<LEN;i++)
printf("%d ",hash[i]);
printf("\n");
printf("输入查找的关键字;");
scanf("%d",&key);
int pos=Haxi_Sou(key); //调用函数在哈希表中查找;
if(pos>0)
printf("查找成功,该关键字在数组中的下标为 %d !!!",pos);
else
printf("查找失败!!!");
printf("\n");
return 0;
}
⭐字符数组、字符串特点及编程注意事项
- 要数组传入一个函数作判断时,需传入数组名和数组长度。
eg
int arr[10];
scanf("%d",&n);
ChooseSort(arr,n)//传入的为数组名arr,而不是arr[]
void ChooseSort(int date[],int n)或(int *p,int n
- static int a[10],可将数组元素全部初始化为0。
- 字符串的输出"%s",字符的输出"%c"。
- 字符串常量:用一对双引号""括起来的字符序列。
- \0--字符串结束符,其等于0,所以判断最后一个元素时可写成s[i]!=0或s[i]!='\0'(注意为单引号,'\0')。
- 字符数组的最后一个元素是'\0',所以char s[N]="Happy"的数组长度为6(还有一个'\0')。
- "a"为字符串,在内存中占两个字节(a,\0);'a'为字符,在内存中只占一个字节(a)。
- 输入:fgets(buf,10,stdin)//buf为数组名,10为数组的最大长度,可接收空格及其他字符。
当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
2.PTA实验作业(7分)
2.1 将数组中的数逆序存放
⭐2.1.1 伪代码
⭐2.1.2 代码截图
⭐2.1.3 找一份同学代码比较,说明各自代码特点
对比与反思
- 我的代码与该同学的代码的区别主要是对逆序的处理方法不同。
- 该同学在输入数组元素后采用逆序的方法直接输出(即从n开始--),而我是采用了两两交换的方法(第一位与最后一位交换,第二位与倒数第二位交换......)对数组重新赋值,最后再输出数组元素。
- 相比之下,我的方法显得更为繁琐,多了许多无意义的步骤,我会争取在后面的编程中改进,写题前尽量思考简便的做法。
2.2 鞍点
⭐2.2.1 伪代码
⭐2.2.2 代码截图
⭐2.2.3 请说明和超星视频做法区别,各自优缺点
- 大体思路相同,均是先找到一行中的最大元素,然后循环判断其与在所在的列上的其他元素,若其是所在列的最小值,则为鞍点,反之不是鞍点。
- 我的写法与超星相似,但在变量名的设计上还有待提高。
- 我们应该注意的是循环中用于标志是否为鞍点的变量flag需在每次循环时重赋值,否则会影响结果。
2.3 切分表达式。
⭐2.3.1 伪代码
⭐2.3.2 代码截图
⭐2.3.3 请说明和超星视频做法区别,各自优缺点
- 超星使用了
continue
语句来提前结束循环,以减少程序运行时间,大大提高了程序的效率。 - 超星将切分表达式所需的代码分装成不同的功能函数,使主函数更加简洁,同时使代码更加清晰易懂,便于读者阅读。
- 我对运算符的分类比超星更少,但没有想到可以使用
continue
语句,编程能力仍需提高,同时超星上的变量命名及功能函数的分装也是我所欠缺的部分。