• 帮初学者改代码——playerc之“练习:求完数问题”(下)


    前文链接:帮初学者改代码——playerc之“练习:求完数问题”(上)

      再来看看be_ferfect()应该如何改。

      be_ferfect()函数的功能是判断number是否为完数,同时把因子对写入divisers数组。以28这个完数为例,在数组中将依次写入

      1 28 2 14 4 7

      输出时则按要求依大小次序输出 1 2 4 7 14。先从前跳到后,到头之后掉头,再从后跳到前。

      这种写入的方式决定了输出代码写起来要困难一些。如果希望输出写得容易些的话,写入时就必须改变这种图省事的办法。

      有很多种方案可选:

      第一种方案,从小到大写

       int divisers_count = 1 ;
       for ( i = 2 ; i < number ; ++ i ){
             if (!( number % i)){ 
     
                divisers[divisers_count ++ ] = i; 
                sum += i;
    
                if ( sum > number ) 
                   return false; 
             } 
       }
    

      这显然简洁多了。作者没有考虑这种方法应该是有自己的想法,估计是认为一对儿一对儿的写更快些。对比一下

       int divisers_count = 2 ;
       
       for ( i = 2 , i_max = sqrt(number)+1 ; i < i_max ; ++ i ){
             if (!(number % i)){ 
     
                divisers[divisers_count ++ ] = i; 
                sum += i;
                
                diviser = number / i ; 
                if ( diviser != i ) { 
                  divisers[ divisers_count ++ ] = diviser; 
                  sum += diviser; 
                } 
                
                if ( sum > number ) 
                 return false; 
             }       
       }

      作者的写法做了大约2√n次除法、求余和不等于运算,而第一种方案要做n-1次除法。作者的写法虽然复杂,但优势还是有一些的。   

      第二种方案,用两个数组存储因子

      1   2   4

      28 14 7

      这样即保留了作者算法的优势,输出的代码也比较容易写。但这要整个地修改代码的基本数据结构,改动比较大。所以这里就不用了。

      第三种方案,从数组两头向中间存储

      1 2 4 0 0 0 …… 7 14

      这种方案,虽然看起来有点别扭,但读写数组都更容易些,也不需要改动数据结构,权衡之下,是唯一较为可取的方案。

      采用这种方案的代码如下: 

    #include <stdio.h>
    #include <stdbool.h>
    
    bool be_ferfect( int , int * , int * );
    void output( int [] , int );
    
    #define TOP (10000) 
    #define DIVISERS_MAX_LENGTH  ((3+1)*(1+1)*(1+1)*(1+1)*(1+1))
    
    int main( void )  
    {  
        int number; 
      
        for( number = 2 ; number < ( TOP + 1 ) ; ++number ){ 
           
             int divisers[DIVISERS_MAX_LENGTH] = { 1 } ; 
             
             if ( be_ferfect( number , divisers , 
                                       divisers + DIVISERS_MAX_LENGTH - 1 ) ){
                 printf("%d ,Its factors are : ", number) ;                         
                 output ( divisers , DIVISERS_MAX_LENGTH ) ;  
             }
        } 
     
      return 0;
    }
    
    bool be_ferfect( int number , int * p_b , int * p_e )
    {
       int i ;
       int sum = * p_b ++ ;
       
       for ( i = 2 ; i * i < number ; ++ i ){
          if ( number % i != 0 )
             continue ;  
             
          sum +=  ( * p_b ++ = i ) + ( * p_e -- = number / i ) ;
          
          if ( sum > number ) 
             return false; 
       }
       
       if ( i * i == number )
           sum += ( * p_b ++ = i) ;
       
       return sum == number ;
    }
    
    void output ( int divisers[] , int size )
    {
       int i ;
       
       for ( i = 0 ; i < size ; i ++ ){
           
          if ( divisers[i] == 0 )
             continue ;
    
          printf ("%d ",divisers[i]); 
       }
       putchar('
    ');
    }
    

     (完)

  • 相关阅读:
    Git使用方法
    设计模式之原型模式
    php基础查找算法
    php基础排序算法
    设计模式之工厂模式
    设计模式之代理模式
    设计模式之装饰者模式
    设计模式之六大原则
    设计模式之策略模式
    设计模式之简单工厂模式
  • 原文地址:https://www.cnblogs.com/pmer/p/3402414.html
Copyright © 2020-2023  润新知