C语言经典题目及解题思路

1、
【问题描述】梯有N阶,上楼可以一步上一阶,也可以一步上二阶。编写一个程序,计算共有多少中不同的走法
【思路】看到此题目容易想到用递归的方法来做,因为递归是一种描述和解决结构自相似问题的基本算法,而N阶楼梯问题和N-1阶、N-2阶的结构完全相同。
     解决递归问题可以分为两个部分,第一部分是一些特殊(基础)情况,用直接法解,即始基;第二部分与原问题相似,可用类似的方法解决(即递归),但比原问题的规模要小。
     定义int count(int n)函数求解N阶楼梯的走法,基于上述思想,可知:

  • N阶楼梯问题的始基是N==1、N==2两种情况;
  • 上楼可以一步上一阶,也可以一步上二阶,当上一阶时问题规模变为N-1,当上二阶时问题规模变为N-2,所以总的情况为count(n-1)+count(n-2)。

【代码】

cCODE:
#include<stdio.h>
#include<stdlib.h>
int count(int n);
/*count how many ways to climb up N steps stairs.*/
int main (int argc, char *argv[])
{
    int n,ct;
    printf("please input n:/n");
    scanf("%d",&n);
    ct=count(n);
    printf("there are %d ways to climb up N steps stairs!/n",ct);
    system("PAUSE");
    return 0;        
}
int count(int n)
{
    if(1==n)
        return 1;
    else if(2==n)
        return 2;
    else return count(n-1)+count(n-2);
}

【程序输入输出】for example
please input n:
5
there are 8 ways to climb up N steps stairs!

2、
【问题描述】Armstrong数具有如下特征:一个n位数等于其个位数的n次方之和。如:
153=1^3+5^3+3^3
1634=1^4+6^4+3^4+4^4
找出2、3、4、5位的所有Armstrong数。
【思路】看到此题我第一反应是用枚举法,给定m(10<=m<=99999),首先判断m的位数n,然后判断它是否等于各位数的n次方之和。

  • 定义函数int judgeDigit(int m),用于判断给定参数m的位数;
  • 定义函数int judgeEqual(int m,int n),其中m为给定的数,n为m的位数,用于判断m是否等于各位数的n次方之和。

【代码】

cCODE:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

int judgeDigit(int m);
/*This function return the digit of parameter m*/

void judgeEqual(int m,int n);
/*parameter m is a integer,parameter n is the digit of m,this function is used to judge m whether is a Armstrong integer and output it*/

int main (int argc, char **argv)
{
    int i,len;
    printf("All 2 digit to 5 digit Armstrong integers are following:/n");
    for(i=10;i<=99999;i++)
    {
        len=judgeDigit(i);
        judgeEqual(i,len);               
    }
    printf("/n");
    system("PAUSE");
    return 0;
}
int judgeDigit(int m)
{/*This function return the digit of parameter m*/
    int len=0;
    do
    {
        ++len;
        m=m/10;
    }while(m);
    return len;
}

void judgeEqual(int m,int n)
{/*parameter m is a integer,parameter n is the digit of m,this function is used to judge m whether is a Armstrong integer and output it*/
    int j,temp=m,sum=0;
    for(j=1;j<=n;j++)
    {
        sum+=(int)(pow(temp%10,n));
        temp=temp/10;
    }
    if(m==sum)/*if m is equal to sum,that is to say m is a Armstrong integer*/
        printf("%d/t",m);
}

【程序输入输出】
no input;
output:
All 2 digit to 5 digit Armstrong integers are following:
153     370     371     407     1634    8208    9474    54748   92727   93084
注:用gcc调试就得不到153这个结果,但windows下用vc6.0就可以得到。不解中,这是编译器问题还是程序问题?
3、
【问题描述】将1,2,3,4,5,6,7,8,9共9个数分成三组,组成3个三位数,且使这3个三位数构成1:2:3的比例,例如:3个三位数192,384,576满足以上条件.192:384:576=1:2:3。试求出所有满足条件的3个三位数。

【思路】1~9组成的最小三位数是123,最大的是987,由于要满足1:2:3的关系,最小的那个数应该不到于987/3=329。这样的话第一个数的 变化范围是123~329,将这里面的数分别乘2、乘3,然后判断这三个数是否符合要求,即这三个数是否由1~9组成,而且各个数字不能相同。
     即对每个数n(123<=n<=329)用枚举法。

  • 定义函数int judge(int n),用于判断整数n的各位数字是否相同,如果有想同的就返回0;否则返回1;
  • 对每个数n(123<=n<=329),2*n,3*n调用judge()函数用于判断这三个数是否由1~9组成且各个数字不相同;
  • 判断n,2*n,3*n这三个数中的各位数是否相同,所以对数n*1000*1000+2*n*1000+3*n调用judge()判断。

所以(judge(n)==0||judge(2*n)==0||judge(3*n)==0||judge(n*1000+2*n*100+3*n)==0)为真的话,即其中给定的n不符合要求。其实只要( judge(n*1000+2*n*100+3*n)==0)这一个条件即可,因为它包含了前面两种情况。   
  caution:其实要判断这三个数是否由1~9组成且各个数组不相同,即这三个数的各位数是否覆盖了1~9,只要判断各位数字的积是否等于9!且各位数字的和是否等于45。
【代码】

cCODE:
#include<stdio.h>
#include<stdlib.h>

int judge(int n);

int main (int argc, char **argv)
{
    int l,m,n,p,q;
    for(l=123;l<=329;l++)
    {
        m=2*l,n=3*l;
        p=l*1000+m,q=p*1000+n;
        if(judge(q)==0)
        //判断l、m、n是否符合要求。如果不符合就跳出本次循环,进入下次循环
            continue;
        printf("%d,%d,%d/n",l,m,n);
    }
    system("PAUSE");
    return 0;
}

int judge(int n)
{//用于判断整数n的各位数字是否相同,如果有想同的就返回0;否则返回1
    int num[10],i,j,len=0,temp=n;
    do
    {
        ++len;
        temp=temp/10;
    }while(temp);//求出n的位数
    for(i=1;i<=len;i++)
    {//将n的各位数字存入num[],并判断是否存在0及相同的数字,如果存在就返回0
        if((num=n%10)==0)
            return 0;
        n=n/10;
        for(j=1;j<i;j++)
            if(num[j]==num)
                return 0;
    }
    return 1;
}

 

cCODE:来自一位网友youshuang ,即用判断各位数字的积是否等于9!且各位数字的和是否等于45。 )
#include <stdio.h>

bool judge( int a, int b, int c )
{
    char tmp_buf[ 10 ];
    sprintf( tmp_buf, "%d%d%d", a, b, c );

    int nTimeResult = 1;
    int nSumResult = 0;
    for ( int i = 0; i < 9; i++ )
    {
        nTimeResult *= ( tmp_buf[ i ] - '0' );
        nSumResult += ( tmp_buf[ i ] - '0' );
    }

    return ( ( nTimeResult == 362880 ) && ( nSumResult == 45 ) );
}

int main()
{
    for ( int i = 123; i <= 329; i++ )
    {
        if ( judge( i, i * 2, i * 3 ) )
        {
            printf( "%d, %d, %d /n", i, i * 2, i * 3 );
        }
    }
    return 0;
}

【程序输入输出】
no input;
output:
192,384,576
219,438,657
273,546,819
327,654,981

4、
【问题描述】和尚挑水
某寺庙里7个和尚:轮流挑水,为了和其他任务不能冲突,各人将有空天数列出如下表:
和尚1: 星期二,四;
和尚2: 星期一,六;
和尚3: 星期三,日;
和尚4: 星期五;
和尚5: 星期一,四,六;
和尚6: 星期二,五;
和尚7: 星期三,六,日;
请将所有合理的挑水时间安排表
【思路】用回朔法求解(递归方式实现,当然也可以用迭代方式)。用结构体存储和尚的信息(空闲时间、是否已经挑过水标记)回朔法即每进行一步,都试图在当 前部分解的基础上扩大该部分解。扩大时,首先检查扩大后是否违反了约束条件,若不违反,则扩大之,然后继续在此基础上按照类似的方法进行,直至成为完整 解;若违反,则放弃该步以及它所能生成的部分解,然后按照类似的方法尝试其他可能的扩大方式,直到尝试了所有的扩大方式。  
【代码】

cCODE:
#include<stdio.h>
#include<stdlib.h>
void backtrack(int n);
/*函数功能:回朔求解第n天至第7天的解(即第n~7天分别安排和尚几)*/
struct st
{
        int spare[8];
/*存储和尚的空闲时间,spare=0表示星期i没有空闲,spare=1表示星期i空闲,其中spare[0]不用*/

        int flag;
/*用于标记和尚周内是否已经工作过,flag=0表示没挑过水,flag=1表示已经挑过水*/

}monk[8];

int x[8],sum=0;/*sum用于统计共有多少种方案*/

int main (int argc, char **argv)
{
        int i,j;        
        for(i=1;i<=7;i++)
        {/*初始化和尚的空闲时间,初始化时和尚全部没挑过水即flag都为0*/
                printf("请输入和尚%d的空闲时间:",i);
                for(j=1;j<=7;j++)
                {
                        scanf("%d",&monk.spare[j]);
                }
                monk.flag=0;
        }
        backtrack(1);        
        printf("共有%d种方案/n",sum);
}

void backtrack(int n)
{/*函数功能:回朔求解第n天至第7天的解(即第n~7天分别安排和尚几)*/
        int j;
        if(n>7)
        {
                sum++;
                printf("方案%d:/n",sum);
                for(j=1;j<=7;j++)
                {                        
                        printf("星期%d和尚%d挑水/n",j,x[j]);
                }               
                printf("/n");
        }
        else
        {
                for(j=1;j<=7;j++)
                {
                        x[n]=j;
                        if(monk[j].flag==0&&monk[j].spare[n]==1)
                        {//判断和尚j是否已经挑过水及和尚星期n是否有空
                                monk[j].flag=1;        
                                backtrack(n+1);        
                                monk[j].flag=0;                                                
                        }                                       
                }        
                                       
        }
}

【程序输入输出】
input:
请输入和尚1的空闲时间:0 1 0 1 0 0 0
请输入和尚2的空闲时间:1 0 0 0 0 1 0
请输入和尚3的空闲时间:0 0 1 0 0 0 1
请输入和尚4的空闲时间:0 0 0 0 1 0 0
请输入和尚5的空闲时间:1 0 0 1 0 1 0
请输入和尚6的空闲时间:0 1 0 0 1 0 0
请输入和尚7的空闲时间:0 0 1 0 0 1 1
output:
方案1:
星期1和尚2挑水
星期2和尚6挑水
星期3和尚3挑水
星期4和尚1挑水
星期5和尚4挑水
星期6和尚5挑水
星期7和尚7挑水

方案2:
星期1和尚2挑水
星期2和尚6挑水
星期3和尚7挑水
星期4和尚1挑水
星期5和尚4挑水
星期6和尚5挑水
星期7和尚3挑水

方案3:
星期1和尚5挑水
星期2和尚6挑水
星期3和尚3挑水
星期4和尚1挑水
星期5和尚4挑水
星期6和尚2挑水
星期7和尚7挑水

方案4:
星期1和尚5挑水
星期2和尚6挑水
星期3和尚7挑水
星期4和尚1挑水
星期5和尚4挑水
星期6和尚2挑水
星期7和尚3挑水

共有4种方案

5、
【问题描述】编写一个 c程序,利用如下的格里高利公式求 п的值,直到最后一项的值小于 10-6为止。


【思路】由公式可以看出, 每次 n的值都会改变,这实际上就是迭代。
在程序设计中,迭代是经常使用的一种算法。使用迭代算法时要注意三个问题:

  • 迭代的初始值,如本题中 sum的初始值为 1 n的初始值为 1
  • 迭代公式,这是迭代的关键,如果有几个迭代公式,要特别注意这些迭代的顺序。如 i+=1 sum+=n的次序不能交换。
  • 迭代终止条件。一般用一个表达式或者计数器来判断迭代式是否应该终止。

本题中迭代式中 i+=1 i的初始值为 1 sum+=n or sum-=n这通过一个标志变量 flag来控制, flag==1 sum+=n flag==0 sum-=n sum的初始值为 1。终止条件为

【代码】

cCODE:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main (int argc, char **argv)
{   
    int flag=0,i=1;
    double n=1,sum=1;
    while(n>=pow(10,-6))
    {
         n=(double)1/(2*i+1);  
         i+=1;               
         if(1==flag)
         {
             sum+=n;
             flag=0;
         }
         else
         {
             sum-=n;
             flag=1;
         }                                       
    }
    sum*=4;
    printf("%lf",sum);                        
    system("PAUSE");
    return 0;
}


【程序输入输出】
No input
Output
3.141595

6、
【问题描述】编写一个 c程序,把下列数组延长到第 50项:
1 2 5 10 21 42 85 170 341 682
【思路】由给定的数组元素可以看出偶数项是前一项的 2倍,奇数项是前一项的 2倍加 1
,这是一中递推关系由前项推出后项,此题可以通过递推关系求解。
       递推解题和迭代解题是很相似的,递推是通过其他变量来演化,而迭代则是通过自身不断演化。递推法的运用也有三个关键:

  • 寻找递推关系。这是最重要的问题。递推关系有解析和非解析两种。解析递推关系是指能用一般数学公式描 述的关系,也称递推公式。例如,本题的递推关系就是解析的。非解析递推关系是指不能用一般的数学公式描述的关系,这类关系的描述,也许本身就是一个过程。 这类问题一般比较复杂,要结合其他的策略如分治法来解决。
  • 递推关系必须有始基,即最小子解(针对初始规模的子解的值),没有始基,递推计算就不能开始。例如本题 a1=1就是始基。
  • 递推计算。即根据递推关系进行递推计算。递推计算可以由递归解析和非递归两种,递归计算是采用递归法,其形式是自顶向下,而非递归则是自底向上。本题是非递归的。

解此题还须注意一点:数列的项必须定义为 double型,因为延长到第 50项如果定义为 int or float型,数列的项会被截断即超过 int float的表示范围。
【代码】

cCODE:
#include<stdio.h>
#include<stdlib.h>

int main (int argc, char **argv)
{

    double a1=1,a=0;
    int i=1;
    while(i<=50)
    {
        printf("%.0lf ",a1); //'.0’ is just for do not output the decimal place
        i++;
        if(i%2==1)
            a=2*a1+1;
        else
            a=2*a1;
        a1=a;   
    }                           
    system("PAUSE");
    return 0;
}

【程序输入输出】
No input
Output
1 2 5 10 21 42 85 .......(略)

7、
【问题描述】 用递归算法实现求一个数组中的最大元素。
【思路】解决递归问题可以分为两个部分,第一部分是一些特殊(基础)情况,用直接法解,即始基;第二部分与原问题相似,可用类似的方法解决(即递归),但比原问题的规模要小。
     本题显然始基是a[0],关键是要找出递归关系,定义一个函数int max(int a[],int n),其中整型a[]是一个数组,n是数组长度减1,即数组最大有效元素的下标,因为c语言中数组元素下标是从0开始的。

 

  • 如果0==n,则a[0]就是最大的元素
  • 如果n>0,则先求出a[0]到a[n-1]的最大元素,然后与a[n]比较,较大者即为最大元素。其中a[0]到a[n-1]又可以用这种方式求,此时需要将a[0],a[1]...a[n-1]看成一个由n-1个元素构成的一维数组。

【代码】

cCODE:
#include<stdio.h>
#include<stdlib.h>

int max(int a[],int n);

int main (int argc, char **argv)
{   
    int a[]={1,2,3,4,5,6,7,6};
    printf("The max element is %d!/n",max(a,7));  
    /*caution:he length of a is 8,but the argument is 7*/              
    system("PAUSE");
    return 0;
}

int max(int a[],int n)
{
    if(0==n)
        return a[n];
    else   
        return (a[n]>max(a,n-1)?a[n]:max(a,n-1));   
}


【程序输入输出】
no input;
output:
The max element is 7!

8、
【问题描述】自然数的拆分:任何一个大于1的自然数N,总可以拆分成若干个自然数之和,并且有多种拆分方法。例如自然数5,可以有如下一些拆分方法:
5=1+1+1+1+1
5=1+1+1+2
5=1+2+2
5=1+4
5=2+3
【思路】自然数的拆分可以用回溯法。
知识点 回 溯法解题时,对任一解的生产,一般采用逐步扩大解的方式。每进行一步,都试图在当前部分解的基础上扩大该部分解。扩大时,首先检查扩大后是否违反了约束条 件,若不违反,则扩大之,然后继续在此基础上按照类似的方法进行,直至为完全解;若违反,则放弃该步以及它生成的部分解,然后按照类似的方法尝试其他可能 的扩大方式,直到已经尝试了所有的扩大方式。
回溯法解题通常包含以下三个步骤:

  • 针对所给问题,定义问题的解空间;如本题对 5的拆分来说, 1<=拆分的数 <=5
  • 确定易于搜索的解空间结构;如本题对 5的拆分来说,用 x[]数组来存储解,每个数组元素的取值范围都是 1<=拆分的数 <=5,从 1开始搜索直到 5
  • 搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。如本题对 5的拆分来说,为了避免重复, x>=x[j](i>j),如 x[]={2,3}满足条件而 x[]={3,2}就不满足条件不是可行解即无效。

回溯法通常有两种实现方式,一种是递归的方式,另一种是迭代的方式。在此就用递归方式,当然迭代的方式也可以。   
【代码】

cCODE:
#include<stdio.h>
#include<stdlib.h>

void splitN(int n,int m);//n是需要拆分的数, m是拆分的进度。
int x[1024]={0},total=0 ;//total用于计数拆分的方法数, x[]用于存储解

int main()
{
    int n ;
    printf("please input the natural number n:");
    scanf("%d",&n);
    splitN(n,1);
    printf("There are %d ways to split natural number %d./n",total,n);
    system("PAUSE");
    return 0 ;
}

void splitN(int n,int m)
{//n是需要拆分的数, m是拆分的进度。
    int rest,i,j;   
    for(i=1;i<=n;i++)
    {// 1开始尝试拆分。         
        if(i>=x[m-1])
        {//拆分的数大于或等于前一个从而保证不重复
            x[m]=i ;//将这个数计入结果中。             
            rest=n-i ;//剩下的数是 n-i,如果已经没有剩下的了,并且进度 (总的拆分个数 )大于 1,说明已经得到一个结果。
            if(rest==0&&m>1)
            {
                total++;
                printf("%d/t",total);
                for(j=1;j<m;j++)
                {
                    printf("%d+",x[j]);
                }
                printf("%d/n",x[m]);
            }
            else
            {
                splitN(rest,m+1);//否则将剩下的数进行进度为 m+1拆分。
            }
            x[m]=0;//取消本次结果,进行下一次拆分。环境恢复,即回溯
        }
    }
}



【程序输入输出】

input:
please input the natural number n:5
output:
1       1+1+1+1+1
2       1+1+1+2
3       1+1+3
4       1+2+2
5       1+4
6       2+3
There are 6 ways to split natural number 5.

 

9、
【问题描述】用递归函数求解两个正整数的最大公约数的过程。
【思路】此题不需太多的思考就是运用欧几里得算法( Euclid’s algorithm)。

  摘自《 The Art  of Computer Programming volume 1
  (Euclid’s algorithm )Give two postive  integers m and n, find their greatest common divisor, that is ,the largest  positive integer that evenly divide both m and n.
  Step1.[Find remainder.]Divide m by n and  let r be the remainder.(We will have 0<=r<n.)
  Step2.[Is it zero?]If r=0,the algorithm  terminates; n is the answer.
  Step3.[Reduce.]Set m=n,n=r, and go back  to Step1.
  

【代码】

  cCODE:  
  #include<stdio.h>
  #include<stdlib.h>
  int GCD(int m,int n);
  /*function is to find the greatest common divisor between mand n*/
  int main (int argc, char **argv)
  {   
      int m,n,temp;
      printf("Please input m and n:/n");
      scanf("%d %d",&m,&n);   
      if(m<n)
      {/*This is just ensure m>n*/
           temp=m;
           m=n;
           n=temp;  
      }
      printf("The greatest common divisor of (%d,%d) is  %d!/n",m,n,GCD(m,n));           
      system("PAUSE");
      return 0;
  }
  
  int GCD(int m,int n)
  {
      if(m%n==0)
           return n;
      else return GCD(n,m%n);
  }
  

【程序输入输出】
Please input m and n:
10 5
The greatest common divisor of (10,5) is 5!

10、

【问题描述】 已知Ackerman函数对于整数m>=0和n>=0有如下定义:

 

ack(0,n)=n+1

 

ack(m,0)=ack(m-1,1)

 

ack(m,n)=ack(m-1,ack(m,n-1))

 

【思路】此题明显用递归方法解,由上述定义可得递归公式如下:

 


          | n+1,               
当m=0时;

 

ack(m,n)= | ack(m-1,1),          当n=0时;

          | ack(m-1,ack(m,n-1)), 其他情况。



【代码】

  cCODE:  
  #include<stdio.h>
  #include<stdlib.h>
  int ack(int m,int n);
  int main (int argc, char **argv)
  {   
      int m,n;
      printf("Please input m and n:/n");
      scanf("%d %d",&m,&n);
      printf("The result of ack(%d,%d) is  %d!/n",m,n,ack(m,n));            
      system("PAUSE");
      return 0;
  }
  
  int ack(int m,int n)
  {
      if(0==m)
           return n+1;
      else if(0==n)
           return ack(m-1,1);
      else return ack(m-1,ack(m,n-1));
  }
  


【程序输入输出】
example 1:
input:
Please input m and n:
0 5
ouput:
The result of ack(0,5) is 6!
example 2:
Please input m and n:
4 0
The result of ack(4,0) is 13!
example 3:
Please input m and n:
2 3
The result of ack(2,3) is 9!

 

//------------------------------------------------------------------------------------//

1、线形表a、b为两个有序升序的线形表,编写一程序,使两个有序线形表合并成一个有序升序线形表h;

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define QUIT 999

typedef struct node
{
  int num;
  struct node* next;
   }NODE;
   
int create_list(NODE** head)
{
  int num;
  int i = 0;
  NODE* p = NULL;
  NODE* q = NULL;
  
  *head = (NODE*)malloc(sizeof(NODE));
  if(*head == NULL)
   {
     printf("head malloc error/n");
     return -1;
     }
   (*head)->next = NULL;
   
   printf("input %d to end add list/n",QUIT);
   while(1)
   {
     p = *head;
     q = (NODE*)malloc(sizeof(NODE));
     if(q == NULL)
     {
      printf("head malloc error/n");
      return -1;
     }
     i++;
     printf("Now Please input num %d:/t",i);
     scanf("%d",&num);
     if(num == QUIT)
       {
         printf("end create list/n");
         break;
        }
     q->num = num;
     while((p->next != NULL) && (p->next->num < num))
      {
        p = p->next;
       }
        
     q->next = p->next;
     p->next = q;
   
    }
   return 0;
}

NODE* merge_list(NODE* head1,NODE* head2)
{
     assert(head1 != NULL);
     assert(head2 != NULL);
     
     
     NODE* head = (NODE*)malloc(sizeof(NODE));
     if(head == NULL)
     {
       printf("head malloc error/n");
       return NULL;
     }
     
     NODE* head_tmp = head;
     NODE* p1 = head1->next;
     NODE* p2 = head2->next;
     
     while((p1 != NULL) && (p2 != NULL))
       {
         printf("p1 data is %d/t p2 date is %d/n",p1->num,p2->num);
         if(p1->num < p2->num)
           {
             printf("copied %d/n",p1->num);
             system("PAUSE");
             head_tmp->next = p1;
             p1 = p1->next;
             }
          else
           {
             printf("copied %d/n",p2->num);
             system("PAUSE");
             head_tmp->next = p2;
             p2 = p2->next;
             }
            head_tmp = head_tmp->next;
         }
         
     if(p1 == NULL)
        {
         head_tmp->next = p2;
         printf("asdas copied:/n");
         print_list(head_tmp);
        }
     else
       {
         head_tmp->next = p1;
         printf("asdas copied:/n");
         print_list(head_tmp);
        }
     return head;
  }
int print_list(NODE* head)
{
   assert(head != NULL);
   NODE* p = head;
   while(p->next != NULL)
    {
      printf("%d/t",p->next->num);
      p = p->next;
      }
   printf("/n");
}

int main(int argc, char *argv[])
{
  NODE* head1 = NULL;
  NODE* head2 = NULL;
  
  create_list(&head1);
  create_list(&head2);

  printf("list1 is:/n");
  print_list(head1);
  printf("list2 is:/n");
  print_list(head2);
  printf("merged list is:/n");
  print_list(merge_list(head1,head2));
   
  system("PAUSE");   
  return 0;
}


2编写算法,从10亿个浮点数当中,选出其中最大的10000个。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//#define INIT 10000

#define INIT 5

//#define TOTAL 100000000

#define TOTAL 10

static int count = 0;

typedef struct tree
{
   int num;
   struct tree* parent;
   struct tree* lchild;
   struct tree* rchild;
  }TREE;
  
TREE* add_tree(TREE** T, TREE* parent, int num)
{
  if(*T == NULL)
   {
     *T = (TREE*)malloc(sizeof(TREE));
     if(*T == NULL)
      {
        printf("malloc error/n");
        return NULL;
        }
        printf("added %d/n",num);
       (*T)->num = num;
       (*T)->parent = parent;
       (*T)->lchild = NULL;
       (*T)->rchild = NULL;
     }
    else if((*T)->num < num)
       return add_tree(&(*T)->rchild,*T,num);
    else
       return add_tree(&(*T)->lchild,*T,num);
}

int midwalk(TREE* T)
{
  if(T!=NULL)
   {
     midwalk(T->lchild);
     count++;
     if(count%10 == 0)
      {
        count = 0;
        printf("%d/n",T->num);
       }
     else
       printf("%d/t",T->num);
     
     midwalk(T->rchild);
     }
   return 0;
}

int tree_out(TREE** T)
{
  int num = 0;
  TREE* p = NULL;
  TREE* q = NULL;
  TREE** tmp = T;
  TREE* tmp1 = *T;
  
  printf("tmp is %p/ntmp1 is %p/n",*tmp,tmp1);
   if(*tmp == NULL)
    {
      printf("sorry the tree is empty/n");
      return -1;
      }
    if((*tmp)->lchild == NULL)
    {
      q = *tmp;
      num = q->num;
      *tmp = (*tmp)->rchild;
      printf("now head is %d/n",q->num);
      free(q);
      q = NULL;
      return num;
      }
    #if 1
    while(tmp1->lchild != NULL)
     {
        p = tmp1;
        tmp1 = tmp1->lchild;
      }
     p->lchild = tmp1->rchild;
    num = tmp1->num;
    free(tmp1);
   #endif
   #if 0
   while((*tmp)->lchild != NULL)
     {
        p = *tmp;
        *tmp = (*tmp)->lchild;
      }
     p->lchild = (*tmp)->rchild;
    num = (*tmp)->num;
    free(*tmp);
   #endif
    return num;
}

int minimum(TREE* T)
{
  while(T->lchild != NULL)
   {
     T = T->lchild;
     }
   return T->num;
}
   
int main(int argc, char *argv[])
{
  int i = 0;
  int num = 0;
  double j = INIT;
  int mini = 0;
  
  
  TREE* T = NULL;
  srand( (unsigned)time( NULL ) );

  for(i=0;i<INIT;i++)
  {
    num = rand();
    add_tree(&T, NULL, num);
   }
   midwalk(T);
   
   mini = minimum(T);
  for(j=INIT;j<TOTAL;j++)
  {
    num = rand();
    if(num > mini)
      {
       tree_out(&T);
       add_tree(&T, NULL, num);
       mini = minimum(T);
      }
   }
   
  midwalk(T);
  system("PAUSE");   
  return 0;
}

原文:http://bbs.chinaunix.net/viewthread.php?tid=1493809

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值