学习c语言的第九天

两个有序序列的中位数 

已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列A0​,A1​,⋯,AN−1​的中位数指A(N−1)/2​的值,即第⌊(N+1)/2⌋个数(A0​为第1个数)。

输入:

输入分三行。第一行给出序列的公共长度N(0<N≤100000),随后每行输入一个序列的信息,即N个非降序排列的整数。数字用空格间隔。

输出:

在一行中输出两个输入序列的并集序列的中位数。

第一版:

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode * Linklist;
struct LNode{
	int Data;
	Linklist Next;
}; 
int main(){
	Linklist L1=(Linklist)malloc(sizeof(struct LNode));
	Linklist L2=(Linklist)malloc(sizeof(struct LNode));	
	Linklist L3=(Linklist)malloc(sizeof(struct LNode));
	Linklist L11=L1,L22=L2;
	L1->Next=NULL;
	L2->Next=NULL;
	L3->Next=NULL;
	int num,count=0,count1=0,count2=0;//count1与count2指的是已经输入的链表个数 
	scanf("%d",&count);//链表长度 
	while(count1<count){
		Linklist q=(Linklist)malloc(sizeof(Linklist));
		scanf("%d",&num);
		q->Data=num;
		q->Next=NULL;
		L11->Next=q;
		L11=q;
		count1++;
	}
	while(count2<count){
		Linklist p=(Linklist)malloc(sizeof(Linklist));
		scanf("%d",&num);
		p->Data=num;
		p->Next=NULL;
		L22->Next=p;
		L22=p;
		count2++;
	}
	L1=L1->Next;
	L2=L2->Next;
	L11=L1;
	L22=L2;
	Linklist L33=L3;
	Linklist w;//定义一个指针方便插入L3 
	while(L11!=NULL&&L22!=NULL){//两个指针在L1和L2中挑取最小值插入L3中 
		if(L11->Data<=L22->Data){
			w=(Linklist)malloc(sizeof(Linklist));
			w->Data=L11->Data;
			w->Next=NULL;
			L3->Next=w;
			L3=w;
			L11=L11->Next;
		}
	   else{
			w=(Linklist)malloc(sizeof(Linklist));
			w->Data=L22->Data;
			w->Next=NULL;
			L3->Next=w;
			L3=w;
			L22=L22->Next;
    	}
   }
	if(L11!=NULL){
		L3->Next=L11;
	}
	if(L22!=NULL){
		L3->Next=L22;
	}
	int i=1;
	L33=L33->Next;
    while(i<(2*num+1)/2) {
		L33=L33->Next;
		i++;
	}
	printf("%d",L33->Data);
}

这道题我最开始是想建立两个链表,把两个链表合并成一个链表,然后再取其中位数,不过发现这道题和前几天的略有不同,前几天的两个链表在输入时都会有结尾的数,比如说遇到-1就结束第一个链表的输入,然后开始第二个链表的输入,但是今天这道题在输入上没有结尾的数字,仅说在两个链表长度相同。同时在排序上也有不同,昨天的是取交集问题,也就是只要有一个链表查找后指针为空了,就不需要继续查找了,但是今天的是合并问题,如果有一个为空还是要继续判断是否有链表里还有数据,如果有的话直接把他们连在新链表后就可以完成。不过我发现虽然我写出来的代码在编译器上是可以正确运行的,而且在PTA平台上可以得出正确的结果,但是在提交后会出现段错误的问题,程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起,所以我打算改变思路。

优化目标:

用两个数组记录输入的数据,再使用与链表相似的合并方式将其合并成为一个新的数组,最后取其中位数。

第二版:

#include<stdio.h>
#include<math.h>
#define N 100
int main(){
	int a[N],b[N],c[N*2];
	int num,i;//num是记录输入多少个数字 
	int q=0,w=0;//相当于标记ab两个数组的指针
	scanf("%d",&num);
	for(i=0;i<num;i++){
		scanf("%d",&a[i]);
	}
	for(i=0;i<num;i++){
		scanf("%d",&b[i]);
	}
	for(i=0;i<2*num;i++){//选最小的一个先写入数组
		if(a[q]<=b[w]){
			c[i]=a[q];
			q++;
		}else {
		c[i]=b[w];
		w++;
     	}
	} 
    printf("%d",c[(2*num-1)/2]);
}

最近一段时间都在学习链表的知识,所以一看到这一类的题目首先就想到了用链表,当时也犹豫了一下觉得这道题不应该这么写,但是也没想到其他的方法,后来发现之前很少使用的数组在这里使用起来真的非常方便。

递归实现顺序输出整数

本题要求实现一个函数,对一个整数进行按位顺序输出。每一位数字从高位到低位顺序打印出来,每位数字占一行。

输入:

一串数字。

输出:

每一位数字从高位到低位顺序打印出来,每位数字占一行。

优化目标:

可能没有优化目标。

#include <stdio.h>

void printdigits( int n ){
	if(n<10){
		printf("%d\n",n);
	}else {
		printdigits(n/10);
		printf("%d\n",n%10); 
	}
}

int main()
{
    int n;
    scanf("%d", &n);
    printdigits(n);
}

 

递归计算Ackermenn函数 本题要求实现Ackermenn函数的计算

输入:

m与n的非负数据

输出:

Ackermenn函数的相应值

优化目标:

可能没有优化目标。

#include <stdio.h>

int Ack( int m, int n );

int main()
{
    int m, n;
    
    scanf("%d %d", &m, &n);
    printf("%d\n", Ack(m, n));
    
    return 0;
}
int Ack( int m, int n ){
    if(m==0){
        return n+1; 
    }else if(n==0&&m>0){
        return Ack(m-1,1);
    }else if(m>0&&n>0){
        return Ack(m-1,Ack(m,n-1));
    }
}

 

递归实现指数函数 

本题要求实现一个计算xn(n≥1)的函数。

输入:

x和n的值。

输出:

xn次幂的值。

优化目标:

可能没有优化目标。

#include <stdio.h>
double calc_pow( double x, int n ){
 int result;
 if(n==1){
  result=x;
 }else{
  result=x*calc_pow(x,n-1);
 }
 return result;
} 
int main()
{
    double x;
    int n;

    scanf("%lf %d", &x, &n);
    printf("%.0f\n", calc_pow(x, n));

    return 0;
}

今天的递归学习感觉还是不够深入,每次看代码的时候都觉得好像不是很难,但是如果是复杂一点的递归自己写起来还是有点混乱,明天会继续递归和树的学习 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值