PAT乙级 1001-1005

本文探讨了使用C语言解决学生信息冒泡排序的问题,重点介绍了字符数组深拷贝的重要性,并分享了一种利用字符指针简化问题的方法。此外,文章深入分析了一个基于Hash表的算法挑战,讨论了如何避免越界错误并提出了链表存储结果的改进方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写了5题才通过了3个,那两个实在不知道怎么回事了?。菜的一笔。

前几个感觉没什么好记录的点,虽然1003还没完全对。后面两个题还是可以记一下

  • 1004
    最近遇到好几个题目都和这个方面有点关联。先是考研的专业课里面,出了一个编程题。说有一个学生信息的结构体,姓名、学号都是字符串存储,然后要将n个学生的信息按照姓名的字典顺序冒泡排序,我一开始想这还不简单。稍微想了一下就开始往试卷上写,写到冒泡的交换的部分时,突然发现这里有个坑。字符数组不能像其他基本类型一样直接赋值,得用strcpy将里面元素逐个拷贝。当时还想牛逼啊,还好看出来了?。考完上实习课的时候,是写一个通讯录,里面的人名等也是用字符串存储,不过老师用的字符指针,存储的时候再申请内存。孤陋寡闻了,第一次看到这样写,貌似这个比我那个写法要高明一些,这下就可以不用考虑那个字符数组深拷贝问题了,可以结构体整体赋值。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct student{
    char *name;
    char *id;
    int score;
}student;


int main()
{
    student *stu;
    student *max,*min;
    int n;
    int i = 0;
    scanf("%d",&n);  
    stu = (student *)malloc(sizeof(student) * n);
    while(n--)
    {
        stu[i].name = (char *)malloc(sizeof(char) * 10);
        stu[i].id = (char *)malloc(sizeof(char) * 10);
        scanf("%s%s%d",stu[i].name,stu[i].id,&stu[i].score);
        if(i == 0)
        {
            max = stu;
            min = stu;
        }
        else
        {
            if(stu[i].score > max->score)
            {
                max = stu + i;
            }
            else
            {
                if(stu[i].score < min->score)
                {
                    min = stu + i;
                }
            }
        }
        i ++;
    }
    printf("%s %s\n%s %s\n",max->name,max->id,min->name,min->id);
    return 0;
}
  • 1005
    这里用的是类似hash表的意思,不过还有错误,等改出来再写上?。
    刚刚看了同学的帖子,恍然大悟?。在此贴上链接https://blog.youkuaiyun.com/qq_36834256/article/details/802325671005. 继续(3n+1)猜想 (25)(可以多多关注欧?)
    我的想法是用两个hash表,一个h[101]用来记录n在计算过程中出现的值,出现了就置1(初始为0),一个result[101]用来记录最后留下的值,每个n来到的时候都将result[n]和h[n]都置1,如果后面的计算过程中h[n]==0,在将h[n] =1,否的话,就将result[n] = 0(从结果中去除)。(这里内存占用就比较多了,再想想看怎么改进一下)。
    我的错误在于当一个数为奇数的时候,下一个数就为(3*n+1)/2,所以就会出现下个值会大于100的情况,而我的哈希表是h[101],会造成越界。测试实例都是比较小的数,而且我后来测试的时候用的比较大的数都是偶数,就不会有越界的情况,答案也是对的,也就搞不懂到底哪里出错了。
    改进的话,再算下一个数的时候,进行一下判断,如果大于100,就continue直接进行再下一个数的计算,不用参与到hash表的判断。
#include <stdio.h>

int main()
{
    int k;
    int n;
    int h[101] = {0};
    int i = 0;
    int result[101] = {0};
    int count = 0;

    scanf("%d",&k);
    for(i; i < k; i++)
    {
        scanf("%d",&n);
        if(h[n] == 0)
        {
            result[n] = 1;
            h[n] = 1;
            count ++;
            while(n != 1)
            {
                if(n % 2 == 0)
                    n = n - n / 2;  
                else
                    n = (3 * n + 1) / 2;
				if(n > 100)//这里就是之后看出错误的地方
					continue;
                if(h[n] == 0)
                    h[n] = 1;
                else
                {
                    if(result[n])
                    {
                        result[n] = 0;
                        count --;
                    }
                    break;
                }
            }
        }
    }
    for(i = 100;i;i--)
    {
        if(result[i])
        {
            printf("%d",i);
            if(count != 1)
            {
                putchar(' ');
            }
            count --;
        }
    }
    return 0;
}


改用链表存储结果的代码

#include <stdio.h>
#include <stdlib.h>
typedef struct res
{
	int n;
	struct res *next;
}res;
void insertLinkList(res *h,int n);
void deleteLinkList(res *h,int n);
int main()
{
    int k;
    int n;
    int h[101] = {0};
    int i = 0;
    int result[101] = {0};
    int count = 0;
	res *l = NULL;
	l = (res *)malloc(sizeof(res));
	if(l == NULL)
	{
		printf("m内存错误\n");
		return -1;	
	}
	l->next = NULL;
    scanf("%d",&k);
    for(i; i < k; i++)
    {
        scanf("%d",&n);
        if(h[n] == 0)
        {
            result[n] = 1;
            h[n] = 1;
            count ++;
			insertLinkList(l,n);
            while(n != 1)
            {
                if(n % 2 == 0)
                    n = n - n / 2;  
                else
                    n = (3 * n + 1) / 2;
				if(n > 100)
					continue;
                if(h[n] == 0)
                    h[n] = 1;
                else
                {
					deleteLinkList(l,n);
                    break;
                }
            }
        }
    }
	res *p = l->next;
	while(p != NULL)
	{
		printf("%d",p->n);
		if(p->next)
			putchar(' ');
		p = p->next;
	}
    return 0;
}

void insertLinkList(res *h,int n)
{
	res* t = (res*)malloc(sizeof(struct res));
	if(t == NULL) 
	{
		printf("内存错误\n");
		return;	
	}
	t->n = n;
	res *pre = h;
	res *p = pre->next;
	while(p)
	{
		if(p->n < n)
			break;
		pre = pre->next;
		p = p->next;
	}
	t->next = p;
	pre->next = t;
}

void deleteLinkList(res *h,int n)
{
	res *pre = h;
	res *p = pre->next;
	while(p)
	{
		if(p->n == n)
			break;
		pre = pre->next;
		p = p->next;
	}
	if(p)
	{
		pre->next = p->next;
		free(p);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值