C语言博客作业04--数组
0.展示PTA总分
1.本章学习总结
1.1 学习内容总结
- 查找数据:
- 二分查找法:适用于规则按照大小顺序排列的整型数列。
- 遍历查找法:运用循环,从数列的第一个开始循环查找。
int BinSearch(int *a,int n,int key,int *count)
{
int left;
int right;
int mid;
left=0;
right=n-1;
while(left<=right)
{
mid=(left+right)/2;
(*count)++;
if(key==a[mid])
{
return mid;
}
else if(key<a[mid])
{
right=mid-1;
}
else
{
left=mid+1;
}
}
return -1;
}
这里是运用是指针实现二分法查找的函数。二分法的具体步骤为:将数组从中间分为左右两边,找到数组的中间数,与需要查找的数对比,若相等,则结束;否则,若比中间数大,去右半边,反之则取左半边。之后重复上述步骤。
- 数组中插入数据
- 方法一:遍历数组,找到对应插入位置后,先将该位置之后所有元素向后移动一位,在将插入元素插入。
- 方法二:重新定义一个数组,找到插入位置后将数字插入并赋值给新数组。
#include<stdio.h>
#define N 10
int main()
{
int n;
int a[N];
int i;
int j;
int x;
int flag = 0;
scanf("%d", &n);
for (i = 0;i < n;i++)
{
scanf("%d", &a[i]);
}
scanf("%d", &x);
for (i = 0;i < n ;i++)
{
if (x > a[i])
{
continue;
}
j = n - 1;
while (j >= i)
{
a[j + 1] = a[j];
j--;
}
a[i] = x;
flag = 1;
break;
}
if (flag==0)
{
a[n] = x;
}/*考虑x是所有数中最大的,放在最后一位或者最小的放在第一位*/
for (i = 0;i < n + 1;i++)
{
printf("%d ", a[i]);
}
return 0;
}
- 数组中数据的删除
- 方法一:直接找到需要删除的元素,从该位置之后开始,使用后一个覆盖掉前一个数,实现删除。
- 方法二:重新定义一个数组,分别按顺序把除了删除数的其他数字赋值给新数组。
#include<stdio.h>
#define N 1000
int main()
{
int n;
scanf("%d", &n);
int i;
int a[N];
int j;
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
int k;
int x;
int t;
scanf("%d", &k);
for (i = 1; i <= k; i++)
{
scanf("%d", &x);
t = x - 1;
for (j = t; j < n-1; j++)
{
a[j] = a[j+1];
}
n--;
}
for (i = 0; i < n-1; i++)
{
printf("%d ", a[i]);
}
printf("%d",a[n - 1]);
return 0;
}
- 数组中的排序方法
- 选择法排序:使用嵌套循环,从第一个数开始,先固定一个数的位置后,从他下一位开始诸逐个比较,找到比他大/小的数便交换,最后实现排序。
- 冒泡法排序:每轮循环会把相邻的两个数进行比较,将大/小的放在后面,逐个比较,最后会将最大/最小的放在最后一位,以此类推。
冒泡法:
#include<stdio.h>
#define N 100
int main()
{
int a[N];
int n;
int k;
scanf("%d %d",&n,&k);
int i;
for (i = 0;i < n;i++)
{
scanf("%d", &a[i]);
}
int item;
int count = 0;
int j;
int temp = n;
for (j = 1;j <= k;j++)
{
for (i = 0;i < temp - 1;i++)
{
if (a[i] > a[i + 1])
{
item = a[i];
a[i] = a[i + 1];
a[i + 1] = item;
}
}
temp--;
}
for (i = 0;i < n-1;i++)
{
printf("%d ", a[i]);
}
printf("%d", a[n-1]);
return 0;
}
- 数组做枚举用法,有哪些案例
- 例如c07-一维数组 7-5 有重复的数据I
代码如下:
- 例如c07-一维数组 7-5 有重复的数据I
#include<stdio.h>
#define MAX 100000
int IsSame(int n);
int main()
{
int n;
scanf("%d", &n);
if (IsSame(n)==1)
{
printf("YES");
}
else
{
printf("NO");
}
return 0;
}
int IsSame(int n)
{
int i;
int data;
static int hash[MAX];
for (i = 0; i < n; i++)
{
scanf("%d", &data);
if (hash[data] == 1)
{
return 1;//有重复
}
else
{
hash[data] = 1;
}
}
return 0;//没有重复
}
为了避免出现运行超时的情况,定义了一个hash数组,即哈希数组,利用数组的下标做枚举法,可以大大的简化代码,减少运行时间。但是该做法有弊端,即只适用于0和正整数,无法处理小数以及负数的情况。
1.2 本章学习体会
学习感受
随着校运会以及大部分活动的结束,部门方面的工作也没有那么忙,终于可以有时间来好好研究代码了。高数,线代,PTA,C语言的复习与做题渐渐安排的有条不紊,似乎在暑假中一股劲写代码的感觉又回来了。由于时间的充足,我开始慢慢学会去优化代码,不在像以前那样只要写的出来就算可以。上次的大作业最后的完成度并不太令我自己满意,一个是完成的太仓促,也有我自己的一个原因,另一个就是我发现自己的思维还是太局限了,比如为什么别人想到使用计时器、使用清屏函数,而我却没有想到呢?所以,一个是思维的局限,另一个可能就是在学习中我开始变得被动,老师说一步我做一步。因此,我要开始慢慢改变自己的思路,在写出题目的同时,多阅读分析别人与自己不同的代码,拓宽自己的思路。
这两周还学习了指针,个人认为自己几乎只学到了一点皮毛,到现在为止感觉自己还是对指针懵懵的,希望尽快通过练习来弥补自己的不足吧。
代码量统计
2.PTA实验作业
2.1 PTA题目1
c07-一维数组
7-5 有重复的数据
本题要求:你的程序首先会读到一个正整数n,1<=n<=100000。 然后是n个整数,这些整数的范围是[1,100000]。如果这些整数中存在重复的,就输出:YES。否则,就输出: NO
2.1.1 伪代码
定义 MAX =100000
定义 IsSame函数
主函数main中:
定义输入的整数个数n 并输入;
if IsSame(n) == 1 then
printf("YES");
else
printf("NO");
end if
return 0;
在函数IsSame(int n)中
定义循环变量i;
定义输入数据data;
定义静态局部变量static int hash[MAX];
for i = 0 to n-1 do
输入整数data
if hash[data] == 1
return 1;//有重复
else
hash[data] = 1;
return 0;//没有重复
2.1.2 代码截图
2.1.3 造测试数据
注:因为在PTA的测试中,有较大n的测试,自己在调试时不方便测试,就没有输入较大n了,但是一样是可以通过的。
2.1.4 PTA提交列表及说明
Q1:在开始的两次编写中,分别是直接写代码与运用函数封装,但是都只是部分正确。
A1:因为不论是直接写还是函数封装,都使用了嵌套2个for循环,在系统使用较大n测试时,造成运行超时。
Q2:之后解决方法。
A2:在看了林丽老师超星平台的视频后,借鉴了老师的思路,在函数中运用判断该数字data对应的数组hash[data]是否为1的巧妙方法,在整体中只使用了 一次循环,简化了代码,最后成功通过。
2.2 PTA题目2
c08-二维数组
7-6 阅览室
天梯图书阅览室请你编写一个简单的图书借阅统计程序。当读者借书时,管理员输入书号并按下S键,程序开始计时;当读者还书时,管理员输入书号并按下E键,程序结束计时。书号为不超过1000的正整数。当管理员将0作为书号输入时,表示一天工作结束,你的程序应输出当天的读者借书次数和平均阅读时间。
注意:由于线路偶尔会有故障,可能出现不完整的纪录,即只有S没有E,或者只有E没有S的纪录,系统应能自动忽略这种无效纪录。另外,题目保证书号是书的唯一标识,同一本书在任何时间区间内只可能被一位读者借阅。
输入格式:
输入在第一行给出一个正整数N(≤10),随后给出N天的纪录。每天的纪录由若干次借阅操作组成,每次操作占一行,格式为:书号([1, 1000]内的整数) 键值(S或E) 发生时间(hh:mm,其中hh是[0,23]内的整数,mm是[0, 59]内整数)每一天的纪录保证按时间递增的顺序给出。
输出格式:
对每天的纪录,在一行中输出当天的读者借书次数和平均阅读时间(以分钟为单位的精确到个位的整数时间)。
2.2.1 伪代码
定义天数n,并输入
定义2000行3列的二维数组record[2000][3] = { {0} ,{0} }并初始化位0;
定义循环变量i = 0;
定义循环变量j = 0;
定义循环变量a = 0;
定义k = 0;
定义书号num;
定义小时,分钟hour, min;
定义借阅控制建位flag;
定义借阅次数count = 0;
定义平均阅读时间avg = 0;
for i = 0 to n do
k = 0;
count = 0;
avg = 0;
while (1)
{
输入("%d %c %d:%d", &num, &flag, &hour, &min);
if num == 0 then
break;//结束工作
end if
record[k][0] = num;
record[k][1] = flag;
record[k][2] = hour * 60 + min;//将输入的书号值赋给数组第一列,建位赋给第二列,时间转化位分钟后赋给第三列
k++;
}
for j = 0 to k do
if record[j][1] == 'S' then
for a = j + 1 to k do
if record[j][0] == record[a][0] && record[a][1] == 'S' then/*当出现同一本书借出后没有还回又输入‘S’或已还回却多次输入‘E’这些不合法输入*/
break;
end if
if record[j][0] == record[a][0] && record[a][1] == 'E' then/*合法输入时,循环找寻书号相同 第二列为‘E’的行*/
count++;
avg = avg + record[a][2] - record[j][2];
break;
end if
end for
end if
end for
if count != 0 then
输出("%d %.0f\n", count, avg / count);
else
输出("0 0\n");//借阅次数为0时
end if
end for
return 0;
2.1.2 代码截图
2.1.3 造测试数据
2.1.4 PTA提交列表及说明
Q1:出现段错误
A1:在访问数组时越界,后经修改后解决
Q2:出现多次的部分正确,几次修改后并没有解决
A2:在观看了林丽老师的视频后,发现是一开始我自己写时函数接口没有处理好,导致传入的参数出现异常,最后只有输出“0 0”是正确的。后来参考了林丽老师的思路,写出了这个不加函数的代码。
2.3 PTA题目3
c09-字符数组
7-7 jmu-c-大数加法
输入2个大数,每个数的最高位数可达1000位,求2数的和。输入格式:保证输入数都是数字,不能有空格。输出格式:输出2数相加的结果
2.3.1 伪代码
#define M 10000
定义全局变量char s1[M], s2[M];
定义全局变量int a[M], b[M], c[M];
定义循环变量 i;
定义变量j, k, n, m;
定义变量 t;
输入两个字符串
memset(c, 0, sizeof(c));//把c的全部函数重置为0
n = strlen(s1);//第一个字符串的长度
m = strlen(s2);//第二个字符串的长度
//printf("s1的长度= %d s2的长度= %d\n", n, m);
for i = 0 to n do
a[i] = s1[n - i - 1] - '0';
end for
for i = 0 to m do
b[i] = s2[m - i - 1] - '0';
/*这两步是将字符串从最后一位开始变成数字后赋给a,b数组 */
if n > m do//第一个数组更长
k = n;
else
k = m;
end if//令k等于长的那个
for i = 0 to k do
c[i] += a[i] + b[i];
if c[i] > 9 then
c[i + 1]++;
c[i] %= 10;
end if//进位
end for
i = k;
while (c[i] == 0)
{
i--;
}/*判断最高位是否有进位。如:若 k=3,如果是100+100,那么c[3]就是0,所以此时没有进位,输出时i从k-1到0输出数组;
如果是900+200,那么那么c[3]就是1,所以此时进位,输出时i从k到0输出数组,所以这也是为什么上面数组加法是要从0到k
进行赋值*/
if (i < 0)
printf("0");
else
for t = i to 0 do
printf("%d", c[t]);//从最后一个开始输出,因为输出的其实是没有间隔的数组,所以避免了直接输出数字的越界问题
end if
printf("\n");
return 0;
2.3.2 代码截图
2.3.3 造测试数据
2.3.4 PTA提交列表及说明
Q1:运行超时
A1:一开始是没有想到使用数组的方式进行输出,还是想使用int,而且在循环方面没有处理好范围,导致了死循环。后来想到数组输出的方法,进行了几次调试,最后成功。
3.阅读代码:
-
代码功能
计算输入算式中的未知数并输出 -
代码优点
- 灵活定义了全局变量,有利于数据在函数之间的传递。
- 封装了多个函数,使主函数更加简洁,将对输入字符串的判断一并写入函数中。在执行完第一个函数内容后返回主函数并前往下一个函数,函数接口处理的十分漂亮。
- 在第一个函数中设置了其他函数,这些函数内容简短但是关键,我们以后也需要学会用更简短的代码达到我们的目的。
- 逻辑条理清晰,想法独特但是易懂,各个函数的功能区分的很明显,函数与函数之间的联系也很紧密,避免了代码的大量重复,值得我们学习。