0.展示PTA总分(0----2)
展示3张关于“数组题目集”分数截图。
1.本章学习总结(2分)
1.1 学习内容总结
整理数组这章学习主要知识点,必须包含内容有:
(1)数组查找数据
- 顺序查找法
顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败。该查找法思路较为简单,容易上手。
/* 举一个例子 */ /*在给定的一组数中查找是否有数字 2*/ #include<stdio.h> int main() { int i; int a[5] = { 1, 2,3,4,5 }; int loc;//记录位置; int flag = 0; for (i = 0; i < 5; i++) { //遍历数组,寻找2; if (a[i] == 2) { loc = i; printf("2在这个数组的第%d项",loc); flag = 1; } } //判断是否发现了数2; if(flag==0) printf("2不在这个数组中。"); }
- 二分查找法
基本思想:也称为是折半查找,属于有序查找算法。确定上界下界(left,right),用给定值k先与中间结点(mid=(left+right)/2)的关键字比较,中间结点把线性数组分成两部分,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪一部分,这样递归进行,直到查找到或查找结束发现表中没有这样的结点。
/*同样举一个例子*/ /*用二分法在一个有序数列{1,2,3,4,5,6,7,8,9,10}中查找key值,若找到key则输出其在数组中对应的下标,否则输出not found。*/ #include <stdio.h> int binarySearch(int a[], int key) { int low = 0; //定义上界下界,他的中间值mid; int high = 9; int mid; int loc; while (low <= high) //循环控制条件,如果下界大于上界则表示可以结束循环; { mid = (low + high) / 2; if (a[mid] < key) low = mid + 1; else if (a[mid] > key) high = mid - 1; //判断在线性数组的哪一部分,然后进行再赋值计算; else { loc = mid ; return loc; } } return 0; } int main() { int i; int key; int a[10] = { 1,2,3,4,5,6,7,8,9,10 }; scanf("%d", &key); if (binarySearch(a, key)) { printf("weizhi:%d", binarySearch(a, key)); } else { printf("not found"); } return 0; }
需要说明的是:使用二分查找法元素必须是有序的,如果是无序的则要先进行排序操作。二分法查找大大减少了用时,是一种高效的查找方法;
(2)数组中如何插入数据
#include<stdio.h> #define N 10 void InputArrery(int a[], int n, int date); int main() { 输入数的个数; for i=0 to i<n; 输入要插入的数date; 调用函数插入InputArrery(a, n, date); 输出数组;//注意插入数之后,项数的改变; } void InputArrery(int a[], int n, int date) { for i=0 to i<n 寻找第一个大于date的数; 记录位置loc=i; end for; 临时变量temp存储date; a[n]=date; for i=n-1 to t>=loc //将每一项的值赋给后面一项,达到插入的目的; a[i + 1] = a[i]; a[i] = temp; }
(3)数组中如何删除数据
- 方法一:移位删除法
思路:有n项的数组将要删除的i项放在数组的最后面,输出的时候只输出n-i项即进行了删除;
int date;//被寻找的数据; int temp; for i=0 to i<n 输入n项数 for i=0 to i<n 遍历数组,寻找值进行交换; if(a[i]==date) temp=a[n-1]; a[n-1]=a[i]; a[i]=temp;//交换数组; for i=0 to i<n-1 输出n-1项数
- 方法二:覆盖法;
int length;//计算数组长度; for int i=0 to i<length-1 for int j=i+1 to j<length //注意:此时第三个表达式空出,因为当找到重复的数据,后面的数往前覆盖之后,应该再进行一次对比 if (a[i] == a[j])//判断如果出现相同数据,则将后面的数据往前移一位 { for int k=j to k<length-1 { a[k]=a[k+1]; } length--;//记录数组长度的变量相应减1 } else j++;//没有的时候才j++; for i = 0 to i<length 输出数组;
(4)数组中排序方法。
- 冒泡法
其原理为从a[0]开始,依次将其和后面的元素比较, 若a[0] > a[i],则交换它们,一直比较到a[n]。同理对a[1], a[2], ...a[n - 1]处理,即完成排序。下面列出其代码:
void bubble(int* a, int n) /*定义两个参数:数组首地址与数组大小*/ { int i, j, temp; for (i = 0; i < n - 1; i++) for (j = i + 1; j < n; j++) /*注意循环的上下限*/ if (a[i] > a[j]) { temp = a[i]; a[i] = a[j]; a[j] = temp; } }
冒泡法原理简单,但其缺点是交换次数多,效率低。
下面介绍一种源自冒泡法但更有效率的方法“选择法”。
- 选择法
选择法循环过程与冒泡法一致,它还定义了记号k = i, 然后依次把a[k]同后面元素比较,若a[k] > a[j], 则使k = j.最后看看k = i是否还成立,不成立则交换a[k], a[i], 这样就比冒泡法省下许多无用的交换,提高了效率。
void choise(int* a, int n) { int i, j, k, temp; for (i = 0; i < n - 1; i++) { k = i; /*给记号赋值*/ for (j = i + 1; j < n; j++) if (a[k] > a[j]) k = j; /*是k总是指向最小元素*/ if (i != k) { /*当k!=i是才交换,否则a[i ] 即为最小*/ temp = a[i]; a[i] = a[k]; a[k] = temp; } } }
(5)数组做枚举用法,有哪些案例?
枚举法:【https://blog.csdn.net/wq3028/article/details/76204690】
程序设计中,存在着一种“数据集”,他的数值在程序中是稳定的,而且元素的个数是有限的,通常可以使用一个数组元素代替一种状态。
---
(6)哈希数组用法
哈希算法:【https://blog.csdn.net/u014209205/article/details/80820263】
应用:hash被用在加密等场合,但在一般的应用程序代码中,也可以用它来存贮简单的数据,这样代码的效率会高很多。
1.2 本章学习体会
- 数组是一种应用性很强的工具。通过对本章内容的学习,可以利用数组解决很多问题。数组就是一种对数据暂时存储的容器,运用它可以同一时间存储多个数据,并且根据要求对所给出的数据进行处理。利用正确的方法可以实现问题快速高效地解决,比如说查找指定数据,可以遍历数组查找,也可以用二分法查找。将数据排序,再也不用设abcd···等多个变量,节约了代码量。并且还可以利用这部分地知识解决实际生活中的问题,比如设计一个最受欢迎节目统计器,寻找多次出现的数据,各种进制之间的相互转换等。最重要的是,利用它可以解决许多线性代数问题(因为它经常研究矩阵)。认真学好这部分的知识对后面指针的学习也有很大帮助。
- 计算这两周代码量
时间 | 代码量 |
---|---|
十一周 | 1203 |
十二周 | 1502 |
2.PTA实验作业(7分)
2.1 题目名1 数组元素的删除
2.1.1 伪代码
int num;//被删除的数据; int temp;//暂时变量,用于交换; for i=0 to i<n 输入n项数 end for 输入要删除的数据;(假设删除i项) for i=0 to i<n 遍历数组,寻找值进行交换; if(a[i]==num) temp=a[n-1]; a[n-1]=a[i]; a[i]=temp;//交换数组;将要删除的数据放在整个数组的后头; end for for i=0 to i<n-i 输出n-i项数
2.1.2 代码截图
2.1.3 造测试数据
测试数据 | 运行结果 | 结果 |
---|---|---|
数的量:10 每个数:1 2 3 4 5 6 7 8 9 10 删除的项:4 3 2 4 6 | 1 4 5 7 8 10 | 正确 |
数的量:2 每个数:1 2 删除的项:1 | 2 | 正确 |
数的量:0 每个数:1 2 删除的项:1 | 乱码 |
2.1.4 PTA提交列表及说明
截图PTA提交列表,介绍碰到问题及解决办法。如:
提交列表说明:
- 1.格式错误:关于结尾有空格的问题,可以让a[0]单独输出;
- 2.答案错误:主要是越界的问题。控制输出的个数;
2.2 题目名2 数组循环左移
2.2.1 数据处理
int n, m;//移动次数; int a[N]; int temp; scanf("%d %d", &n, &m); for i = 0 to i < n { 输入数据; } end for for i = 1 to i<= m { temp = a[0];//储存头号数据; for k = 0 to k < n 进行后一项与前一项的交换; } end for for i = 0 to i < n - 1 { 输出结果; } end for;
2.2.2 代码截图
2.2.3 造测试数据
测试数据 | 运行结果 | 结果 |
---|---|---|
输入几个数:8 移动几次:3 数:1 2 3 4 5 6 7 8 | 4 5 6 7 8 1 2 3 | 正确 |
输入几个数:2 移动几次:3 数: 5 6 | 6 5 | 正确 |
2.2.4 PTA提交列表及说明
- 1.多种错误:刚开始的时候没有思路,一直想把前面几项当成一个整体进行移动,但是多种错误;
- 2.答案正确:后来在网上搜到了整体移动的方法;
- 3.答案正确:看了超星平台的视频之后,感觉每次只移动一个数字,多次进行移动的效率高,且容易理解;
2.3 题目名3 阅览室
2.3.1 数据处理
int main() { scanf("%d", &n);//输入要查找N天的纪录; for i = 1 to i <= n { k = 0; while (1) { scanf("%d %c %d:%d", &number, &op, &hour, &minute); if (number == 0) break; //输入0则表示退出; record[k][0] = number; record[k][1] = op; //利用二维数组进行数据的存储; record[k][2] = hour * 60 + minute; k++; } AverageTime(record, k); } return 0; } void AverageTime(int record[][3], int k)//向下查找并且进行计算; { for i = 0 to i < k { if (record[i][1] == 'S')//以S为开始; { for j = i + 1 to j < k { if (record[j][0] == record[i][0] && record[j][1] == 'S') break; if (record[j][0] == record[i][0] && record[j][1] == 'E')//以E 为结束; { count++; avg = avg + record[j][2] - record[i][2]; break; } } end for } } end for }
2.3.2 代码截图
2.3.3 造测试数据
/*1 S 08:10 //测试数据(1) 2 S 08:35 1 E 10:00 2 E 13:16 0 S 17:00 0 S 17:00 3 E 08:10 1 S 08:20 2 S 09:00 1 E 09:20 0 E 17:00*/
测试数据 | 运行结果 | 结果 |
---|---|---|
测试数据(1) | 2 196 0 0 1 60 | 正确 |
0(表明没有查询) | 正确 |
2.3.4 PTA提交列表及说明
- 1.多种错误:刚开始的时候没有思路;
- 2.编译错误:ctrl+v时候发生了错误;
- 3.答案正确:看了超星平台的视频之后,按照老师给的思路进行了编译,最后成功完成了代码;
3.阅读代码(-2--1分)
打印螺旋方阵———洋葱遍历法;
题目描述:
遍历方式:
优点:
- 该代码运用了很详细的注释,比较直观的描述了数组打印的过程;
- 总体思路上来讲,将数组从外层到内层不断地存放,打印出一个矩形(n为其边长),外面有一个大的for循环,判断循环结束的条件是是s>e;解决了我pta上没有解决的内容。
我的代码:
更加优雅的解题方法:
核心思路:
当我们遍历每一行、每一列时,都把最后一个元素留着,等到下一步再遍历。这样的话,我们每次把矩阵剥离一圈,都对应 4 个非常规整的循环,边界条件清晰不易出错。