• 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
        代码如下:
    #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
    ", count, avg / count);
    	else
    		输出("0 0
    ");//借阅次数为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, 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("
    ");
    
    return 0;
    
    

    2.3.2 代码截图

    2.3.3 造测试数据

    2.3.4 PTA提交列表及说明

    Q1:运行超时
    A1:一开始是没有想到使用数组的方式进行输出,还是想使用int,而且在循环方面没有处理好范围,导致了死循环。后来想到数组输出的方法,进行了几次调试,最后成功。
    


    3.阅读代码:

    • 代码功能
      计算输入算式中的未知数并输出

    • 代码优点

      • 灵活定义了全局变量,有利于数据在函数之间的传递。
      • 封装了多个函数,使主函数更加简洁,将对输入字符串的判断一并写入函数中。在执行完第一个函数内容后返回主函数并前往下一个函数,函数接口处理的十分漂亮。
      • 在第一个函数中设置了其他函数,这些函数内容简短但是关键,我们以后也需要学会用更简短的代码达到我们的目的。
      • 逻辑条理清晰,想法独特但是易懂,各个函数的功能区分的很明显,函数与函数之间的联系也很紧密,避免了代码的大量重复,值得我们学习。
  • 相关阅读:
    jvm 垃圾收集器
    MySQL 查询结果去除边框
    MySQL5.7 半同步复制技术
    MySQL 5.7半同步复制技术 zero
    redis 迁移工具 redisshake
    MySQL 如何找出占用CPU较高的SQL
    部署redis sentinel
    MySQL的SQL_CALC_FOUND_ROWS 类似count(*)
    MongoDB 副本集删除超级用户后恢复
    【Linux】关于 Systemd/Journal
  • 原文地址:https://www.cnblogs.com/caihaoweideboke/p/11872198.html
Copyright © 2020-2023  润新知