C语言博客作业04--数组
0.展示PTA总分
- 一维数组
- 二维数组
- 字符数组
1.本章学习总结
1.1 学习内容总结
-
数组的查找通常是用下标,也可以用新学的指针来查找。
使用下标的话,可以使用顺序查找法,即从头到尾扫描
也可以用二分查找法,逐渐缩小查找范围的方式 -
数组中如何插入数据
-
伪代码:
定义insertPosition,用来表示插入的数据
要插入的数据为x
第一个for循环:让x与数组中每个数比较,比它大时insertPosition改变为该数组后一位的下标
第二个for循环:让数组从后往前依次得到它前面的数的值,达到后移一位的效果
最后将该插入的x放入insertPosition下标的对应的位置 -
删除数据的做法
1.重构数组
即在原来的数组上进行修改
这样做的缺点是会破坏原来的数组
一维数组的数据元素删除(7-6)比较简单,因为直接对应下标,直接左移数组即可
代码截图:
若是要对某个数据进行删除,则需要先扫描到该数据对应的下标并传入deleteIndex
2.构建新数组存放
这个做法就要好许多,除非题目有特殊要求只能在原数组上修改
因为这个做法的优点是可以保留原数组,只要将除了要删除的数据存入新构建的数组中即可
不过在做连续删除的时候会不如第一种做法 -
目前学到的排序方法主要有两种,一种是冒泡排序法,一种是选择排序法
选择排序法的思路是:将第一个数a[0]与后面所有的数比较,找到最小或者最大的数放在第一个数a[0]的位置;第二次从第二个数a[1]开始,将找到的次大或次小的数放在a[1],以此类推
冒泡排序法的思路是:将a[0]与a[1]比较,小的放前面,大的放后面,再将a[1]与a[2]比较,以此类推,直到把最大的数放在最后,然后选出第二大的数,以此类推
两种做法各有优缺点 -
数组做枚举用法
课堂派上做的进制转换的题(找不到在哪就没放图) -
哈希数组
可用于统计输入的某个数据的次数
pta上一维数组7-9调查电视节目的受欢迎程度就可以用这种做法
其中还有一维数组7-5有重复数据这题
这里利用的是将数据输进新数组中唯一的位置上,扫描当前数据与新数组中对应位置的数据是否相等并判断的做法
1.2本章学习体会
- 课堂派做题的时候,经常会遇到一些书上没有的知识,老师在课堂上有时也没有讲到
- 1269行,未达标
2.PTA实验作业
2.1一维数组7-5有重复数据
2.1.1伪代码
定义一个常量N 100001(足够大)
定义a[N]储存N个数
定义c[N]储存N个数,并赋予全部初值0
定义flag记录是否重复,赋值为0
输入要输入的个数n
for int i=0 to i<n
输入a[i]
end for
for i=0 to n-1
if(a[i] == c[a[i]]) then
flag=1
break
end if
c[a[i]] = a[i];
end for
if(flag==1) then
printf("YES")
else
printf("NO")
end if
- 思路:把第一次出现的数存入c[N]当中,数据是多少就存放在哪个位置,当有相同数据进入时,如果c[N]中已经有这个数,那么flag=1,并输出YES,完全没有重复,flag不变,为0,输出NO
- 这题其实是哈希数组的应用
2.1.2代码截图
2.1.3造测试数据(太大的不方便造,这里只展示部分小数据)
输入数据 | 输出数据 | 长长的标题3 |
---|---|---|
5 1 2 3 1 4 |
YES | 正常数据 |
5 1 5 6 8 9 |
NO | 正常数据 |
1 5 |
NO | 单个数据 |
2.1.4PTA提交列表及说明
1-3部分正确:前两个测试点正确,最后一个测试点超时,即老师在超新星平台上提到的当N最大时循环次数过多的超时问题,这三次错误是我在循环嵌套的基础上进行修改
4.答案错误:完全推翻重打,利用哈希数组,改成了单层循环,什么都加了,就是忘记打上两个printf...
5.答案正确:加上两个printf后,因为是单层循环,测试点三不会超时就过了
2.2二维数组7-6阅览室
2.2.1伪代码
定义常量M2000
定义天数n
定义一天内借书的次数count=0
定义天数计数count_n=0//当该数等于天数n时结束循环
定义flag//用于忽略无效记录
定义小时hour,定义分钟minute
定义一天总时间time
定义一天平均时间AVerageTime=0
定义operation//存放当前操作是S或E
定义数组a[M][2]//第一列存储书名,第二列存储时间(统一分钟)
定义数组b[M]
定义数组c[M],初值全为0
while (count_n != n)
输入a[i][0],operation,hour,minute
a[i][1]=hour换算成分钟加minute
if (operation == 'S' && a[i][0] != 0) then
flag++;//每次输入增加1
count++;
b[a[i][0]] = a[i][1];
c[a[i][0]] = 1;
end if
if (operation == 'E' && flag != 0 && a[i][0] != 0 && c[a[i][0]] != 0) then
flag--;//每次有效输入(即不重复)减少1
b[0] = a[i][1];
time += b[0] - b[a[i][0]];
c[a[i][0]] = 0;//防止同一书名的重复输入
end if
if (a[i][0] == 0) then
if (flag != 0) then//当flag不等于0时,说明输入的S和E不对等
清除多余的S输入导致的count++
end if
if(count != 0) then
计算一天平均阅读时间
else
平均阅读时间为0
end if
输出一天借书的次数count和平均阅读时间AverageTime
count = 0;
count_n++;//累计输入n次0,即n天,就结束循环
time = 0;
flag = 0;
end if
end while
2.2.2代码截图
2.2.3造测试数据
2.2.4PTA提交
1.部分正确:没处理无效的S或E的重复输入,导致程序出错
2.部分正确:测试数据中的第二天无输入处理不当,导致结果为1,0,实际应为0,0,原因是没有对count进行清零
3.编译错误:复制代码时不小心把其中一个分号改成了中文的
4.答案正确:详细修改并改好细节后正确
2.3字符数组7-2IP地址转换
2.3.1伪代码
定义数组base[33]
定义四个ip1,2,3,4,都=0
输入32位二进制字符串
for int i=0 to 32
if(i <= 7) then
每个数乘2的n次方,n为该数的位数-1(每8个数一组,第一个数为8位)
ip1 += (base2[i] - '0') * pow(2, 7 - i);
else if(i > 7 && i <= 15)
ip2 += (base2[i] - '0') * pow(2, 15 - i);
else if(i > 15 && i <= 23)
ip3 += (base2[i] - '0') * pow(2, 23 - i);
else
ip4 += (base2[i] - '0') * pow(2, 31 - i);
end if
end for
输出ip地址
2.3.2代码截图
2.3.3造测试数据
输入数据 | 输出数据 | 说明 |
---|---|---|
11001100100101000001010101110010 | 204.148.21.114 | 测试数据 |
全为1 | 255.255.255.255 | 极限数据 |
全为0 | 0.0.0.0 | 极限数据 |
2.3.4PTA提交列表及说明
1.部分正确:base定义为32导致输入全为1时最后一个ip会变成254
2.答案正确:修改了base为33,多给了个位置,修正错误
3.阅读代码
- 代码功能:把26个字母按顺时针顺序输出,如果不够,再次从A开始(不限于正方形矩阵)
- 优点:充分利用数组的功能,结构工整,合适的换行和注释使代码不会拥挤,看起来很舒适