C语言编程练习day3

1、大数的阶乘。比如大于10小于1000;

解题过程。我在PTA上做这个题的时候,由于题上的示例输入为15!=1307674368000。所以就一直用15来练习。刚开始的时候由于int类型为21亿多,所以输出的时候超出范围,被截断,答案就不正确。然后,用来long long 类型来表示,其范围在(-2^63~~2^63-1),就能够表示15!。(注意:long long在打印时应该是printf("%lld", N);要在%d前加”ll“)。然后在PTA上测试,结果显示为部分正确,如果取最大值,即计算999!时,long long 类型仍然不能输出(double也超出了范围)。最后通过网上查阅,许多博主的建议是通过数组来存,最后看了一篇通过int类型数组的解决方案的博客,最后成功解决。

思路1:通过long long(或double)类型,能够部分解决,对于太大的数,比如结果超过(-2^63~~2^63-1)的,仍然不行。代码如下

#include <stdio.h>

//打印非负整数的阶乘
void Print_Factorial ( const int N ){

	if(N > 0){
		long long result = 1; //当超出long long时,仍然不行
		for(int i=0; i<N; i++){
			result *= i+1;
		}
		printf("%lld\n", result);
	}
    else if(N==0)
        printf("1");
    else if (N<0){
        printf("Invalid input");
    }
}

int main(){

	int N;
	scanf("%d", &N);
	Print_Factorial(N);
	
	return 0;
}

思路2:借鉴了网上的写法,通过一个数组来存阶乘结果。代码如下

#include <stdio.h>

//打印非负整数的阶乘
void Print_Factorial ( const int N ){

	if(N > 0){
	int a[3000];
	int temp,num,digit;           //temp:每一位的结果  num:进位   digit:结果的位数
	int i,j;
	a[0]=1;
	digit=1;                      //从第1位开始 
    if(N>0){
       for(i=2;i<=N;i++){
	    	num=0;
			for(j=0;j<digit;j++){
			  temp=a[j]*i+num;    //+num:表示a[j]有进位,a[j+1]就应该加上num
			  a[j]=temp%10;       //把当前位的数字存入数组 
			  num=temp/10;        //向前面一位进位 
		    } 
		    while(num){           //当i的阶乘算完,仍有进位,则数组需扩大 
		    	a[digit]=num%10;
		    	num/=10;
		    	digit++;
			}
		}
		for(i=digit-1;i>=0;i--){
			printf("%d",a[i]);
		}
	}
    else if(N==0)
        printf("1");
    else if (N<0){
        printf("Invalid input");
    }
}

int main(){

	int N;
	scanf("%d", &N);
	Print_Factorial(N);
	
	return 0;
}

大数阶乘结果:比如999!为

 2、实现判断给定整数奇偶性的函数。

思路:如果n % 2 =0 那么n为偶数,否则为奇数

#include <stdio.h>

int even( int n ){
	if(n % 2 ==0){
		return 1;
	}else{
		return 0;
	}
}

int main(){
	int N;
	scanf("%d", &N);
	if(even(N)){
		printf("%d is even.\n", N);
	}else{
		printf("%d is odd.\n", N);
	}
	
	return 0;
}

3、实现一个函数,求N个集合元素A[]的中位数,即序列中第⌊(N+1)/2⌋大的元素。其中集合元素的类型为自定义的ElementType

思路:找中位数,首先将数组A排序,然后找到中间位置,然后返回。我这里采用"快速排序"。

#include <stdio.h>

#define MAXN 10

typedef float ElementType;

//快速排序
void QuickSort(ElementType A[], int start, int end){
	int i = start;
	int j = end;
	ElementType temp = A[start];
	if(i<j){
		while(i<j){
			//右半部分
			while(i<j && A[j]>=temp){
				j--;
			}
			if(i<j){
				A[i] = A[j];
				i++;
			}
			//左半部分
			while(i<j && A[i]<=temp){
				i++;
			}
			if(i<j){
				A[j] = A[i];
				j--;
			}
		}
		A[i] = temp; //枢轴元素填入i=j的位置
		//再递归排序左、右部分
		QuickSort(A, start, i-1);
		QuickSort(A, j+1, end);
	}
}

/*
	求数组A中元素的中位数,N表示A中元素个数
	思路:将数组A排序
		  A长度为基数,则中位数为A[N / 2]
		  A长度为偶数,则中位数为(A[N / 2 - 1] + A[N / 2]) /2
*/

ElementType Median(ElementType A[], int N){
	ElementType result;
	//将数组A排序,采用快速排序
	QuickSort(A, 0, N-1);
	
	if(N % 2 == 0){
		result = (A[N / 2 - 1] + A[N / 2]) / 2;
	}else{
		result = A[N / 2];
	}
	return result;
}

int main(){
	ElementType A[MAXN] = {0};
	int N;
	scanf("%d", &N);
	for(int i=0; i<N; i++){
		scanf("%f", &A[i]);
	}
	
	printf("%.2f\n", Median(A, N));
	
	return 0;
}

4、

将N个整数按从小到大排序的冒泡排序法是这样工作的:从头到尾比较相邻两个元素,如果前面的元素大于其紧随的后面元素,则交换它们。通过一遍扫描,则最后一个元素必定是最大的元素。然后用同样的方法对前N−1个元素进行第二遍扫描。依此类推,最后只需处理两个元素,就完成了对N个数的排序。

本题要求对任意给定的K(<N),输出扫描完第K遍后的中间结果数列。

注意:对于冒泡的核心部分当采用从左往右遍历时。内层循环变量j应该从1开始,并且要if(A[j-1]>A[j])作为判断条件

for(int i=0; i<K; i++){//冒泡排序核心算法
        for(int j=1; j<N-i; j++){
            if(A[j-1]>A[j]){
                int temp = A[j-1];
                A[j-1] = A[j];
                A[j] = temp;
            }
        }
    }

有问题的写法:

for(int i=0; i<K; i++){//冒泡排序核心算法
        for(int j=0; j<N-i; j++){
            if(A[j]>A[j+1]){
                int temp = A[j+1];
                A[j+1] = A[j];
                A[j] = temp;
            }
        }
    }

如果j从0开始,并且A[j]>A[j+1]作为判断条件的话,当j=N-1时,j+1时数组就已经越界了。在PTA就不能排序成功,而在dev c++上还是能正确,所以要注意。

正确的完整代码:

#include <stdio.h>

int main(){
    
    int N, K;
    scanf("%d%d", &N, &K);
    
	int A[N];
    for(int m=0; m<N; m++){
        scanf("%d", &A[m]);
    }
    for(int i=0; i<K; i++){//冒泡排序核心算法
        for(int j=1; j<N-i; j++){
            if(A[j-1]>A[j]){
                int temp = A[j-1];
                A[j-1] = A[j];
                A[j] = temp;
            }
        }
    }
    for(int n=0; n<N-1; n++){
        printf("%d ", A[n]);   
	}
    printf("%d", A[N-1]);
    return 0;
}

注意事项:平时在dev c++运行代码时,对printf("%d ", A[n])输出,在输出最后一个数后还会有一个"空格",在控制台感觉没有什么问题。而在PTA上,可能他的校对方式的局限,最后的一个输出,还要单独写 printf("%d", A[n])。

总结:今天代码写的有点艰难,对大数的处理不太熟练,甚至说在今天之前毫无头绪。在超过了long long 或double类型数据时,就应该通过数组来存储数据了。除此之外,对于数组越界的问题也应该考虑,不然写的代码就有问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别偷我的猪_09

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值