本文前一部分的链接
http://www.cnblogs.com/KBTiller/archive/2011/06/07/2074344.html
21.记录结果
由于无法保证输出的结果有序,所以只能把计算结果存储起来,待全部计算完毕再输出。
事先也无法知道花朵数的个数,所以链表是比较适宜的存储方式。这种方案同时很容易保证保证有序存储。
可以考虑用返回值的办法返回这个链表的head,也可以在main()中定义这个head,向qiongju()和xunhuan()传递&head。但是不难发现这两种方案参数总是要经历一系列无谓的传递,由于嵌套深度较深,求出结果的位置距离main()很远,所以不考虑这样的方案。代之以外部变量方案。
首先在xunhuan()中写出函数调用语句及函数原型
jilu( & he ); // void jilu( DASHU * ); //<=>记录结果
把// void jilu( DASHU * ); 移动到"2_穷举.h"中,此后"2_穷举.c"变为
/*2_穷举.c*/
#include "2_穷举.h"
#include "0_问题.h"
typedef unsigned int SHUZI_GESHU[JINZHI];
//SHUZI_GESHU[d]存储数字d的个数
typedef DASHU SHUJUBIAO[JINZHI-1][WEISHU + 1];
//0*(JINZHI-1)^N 1*(JINZHI-1)^N ……WEISHU*(JINZHI-1)^N
//0*(JINZHI-2)^N 1*(JINZHI-2)^N ……WEISHU*(JINZHI-1)^N
//……
//0*(1)^N 1*(1)^N ……WEISHU*(1)^N
static void xunhuan(const int , const int , DASHU (*)[WEISHU + 1] ) ;
static void jianli_sjb ( SHUJUBIAO * * ); //建立数据表
static SF wenhe( SHUZI_GESHU * const , const DASHU * const);
static SF wenhe( SHUZI_GESHU * const p_sz_gs ,
const DASHU * const p_he )
{
int sz_gs_he[JINZHI] = { 0 }; //和中各数字的个数
if( chaoguo_W(p_he) == SHI // 超过W位 || 不足W位
|| buzu_W (p_he) == SHI ){
return FOU ;
}
qiu_sz_gs( &sz_gs_he , p_he ); // 求和中各数字的个数
if ( memcmp ( sz_gs_he , *p_sz_gs , sizeof sz_gs_he )==0 ){
return SHI ;
}
return FOU ;
}
//建立数据表
static void jianli_sjb ( SHUJUBIAO * * p_p_sjb )
{
if( (* p_p_sjb = malloc(sizeof(SHUJUBIAO)) ) == NULL ){ //#include <stdlib.h>
exit(!EXIT_SUCCESS);
}
{
int i , j ;
for( i = 0 ; i < JINZHI - 1 ; i ++){
ds_fuzhi( *( * * p_p_sjb + i ) + 0 , 0 );//第一列为0
ds_fuzhi( *( * * p_p_sjb + i ) + 1 , 1 );//第二列先赋值为1
for( j = 0 ; j < N ; j ++ ){ //求N次幂
ds_chengyi( *( * * p_p_sjb + i ) + 1 , JINZHI - 1 - i );
}
for( j = 2 ; j <= WEISHU ; j ++ ){
(*( * * p_p_sjb + i ))[j] = (*( * * p_p_sjb + i ))[j-1] ;
ds_jiaru ( *( * * p_p_sjb + i ) + j , *( * * p_p_sjb + i ) + 1 ) ;
}
}
}
}
extern void qiongju( void )
{
SHUJUBIAO *p_sjb = NULL ;
jianli_sjb ( & p_sjb ); //建立数据表
xunhuan( WEISHU , JINZHI-1 , *p_sjb ) ;
free ( p_sjb );
}
static void xunhuan( const int gssx /*个数上限*/,
const int sz /*关于哪个数字*/,
DASHU (*p_hang)[WEISHU + 1] /*指向一行数据*/)
{
static DASHU he = { { 0 } } ;//static DASHU he ; // =0 待完成
DASHU he_ = he ; //记录累加前的值
static SHUZI_GESHU sz_gs ;
if( sz > 0 ){
int i;
for( i = 0 ; i <= gssx ; i++ ){
sz_gs[sz] = i ; //记录数字的个数
ds_jiaru ( &he , *p_hang + i ) ;
xunhuan( gssx - i , sz - 1 , p_hang + 1 );
he = he_ ; //恢复原来的值
}
}
else{
sz_gs[sz] = gssx ; //记录数字的个数
if( wenhe ( & sz_gs , &he ) == SHI ){ //验算两者是否"吻合"
jilu( & he ); //<=>记录结果
}
}
}
考虑在另一个模块完成这个函数,为此在工程中添加"4_结果.h"。
在"2_穷举.h" 中 // void jilu( DASHU * ); 之前加上 #include "4_结果.h",并把 // void jilu( DASHU * ); 复制到 "4_结果.h" 中,此后"2_穷举.h"变为
/*2_穷举.h*/
#ifndef QIONGJU_H
#define QIONGJU_H
/**************************类型定义**************************/
#include "3_大数.h"
#include "常用.h"
/**************************函数原型**************************/
extern void qiongju( void );
#include <stdlib.h> //malloc()
#include <string.h> //memcmp()
#include "4_结果.h" //void jilu(DASHU * );
#endif // QIONGJU_H
在 "4_结果.h" 中将 void jilu(DASHU * ); 改写为
extern void jilu(DASHU * );
并在其前面添加 #include "3_大数.h" 预处理命令。此时"4_结果.h"的内容为
/*4_结果.h*/
#ifndef JIEGUO_H
#define JIEGUO_H
/**************************类型定义**************************/
#include "3_大数.h"
/**************************函数原型**************************/
extern void jilu( DASHU * );
#endif // JIEGUO_H
在工程中添加"4_结果.c",在"4_结果.c"定义extern void jilu( DASHU * );
/*4_结果.c*/
#include "4_结果.h"
extern void jilu( DASHU *p_ds )
{
}
由于链表很容易实现把数据依照顺序排列,所以采用链表存储已经求出的花朵数。首先定义节点的数据类型
/*4_结果.h*/
#ifndef JIEGUO_H
#define JIEGUO_H
/**************************类型定义**************************/
#include "3_大数.h"
typedef struct jd {
DASHU hds; //花朵数
struct jd *xiayige; //下一个
}
JIEDIAN;
/**************************函数原型**************************/
extern void jilu( DASHU * );
#endif // JIEGUO_H
定义“头”的位置:由于main()中有函数需要使用,且用函数返回值的办法传回过于繁琐也很不自然,所以这里使用外部变量。但将其作用范围限制在仅仅模块内能使用(static)。下面是加入了一个节点的代码及测试代码
/*4_结果.c*/
#include "4_结果.h"
static JIEDIAN *tou = NULL ;//头 //在4_结果.h中加入 #include <stdlib.h>
extern void jilu( DASHU *p_ds )
{
JIEDIAN **p_t = &tou ;
JIEDIAN *p_jd = NULL ;
if((p_jd=malloc( sizeof (JIEDIAN ) ))==NULL ){ // 添加节点
printf("无法存储");
exit(1);
}
else{
p_jd->hds = *p_ds ; //写入节点
}
while ( *p_t != NULL
/* || (*p_t)->hds 小于 *p_ds */ ) {
p_t = &(*p_t)->xyg ;
}
//加入到链表中
p_jd -> xyg = * p_t ;
* p_t = p_jd ;
#ifdef CESHI
ds_shuchu( &tou->hds );
system("PAUSE");
exit(2);
#endif
}
测试输出153,测试通过。
其中还有一个判断一大数是否小于另一大数的函数尚未完成,依照下面次序完成:
在本地写函数调用—>在本地写函数原型—>将函数原型移动到"4_结果.h"
此时"4_结果.c"为
/*4_结果.c*/
#include "4_结果.h"
static JIEDIAN *tou = NULL ;//头 //在4_结果.h中加入 #include <stdlib.h>
extern void jilu( DASHU *p_ds )
{
JIEDIAN **p_t = &tou ;
JIEDIAN *p_jd = NULL ;
if((p_jd = malloc( sizeof (JIEDIAN ) ))==NULL ){ // 添加节点
printf("无法存储");
exit(1);
}
else{
p_jd->hds = *p_ds ; //写入节点
}
while ( *p_t != NULL
|| ( xiaoyu(&(*p_t)->hds , p_ds ) == SHI ) // #include "常用.h"
/* || (*p_t)->hds 小于 *p_ds */ ) {
p_t = &(*p_t)->xyg ;
}
//加入到链表中
p_jd -> xyg = * p_t ;
* p_t = p_jd ;
#ifdef CESHI
ds_shuchu( &tou->hds );
system("PAUSE");
//exit(2);
#endif
}
->在"4_结果.h"中加上
#include "3_大数.h"
之后将函数原型移动到"3_大数.h"
/*4_结果.h*/
#ifndef JIEGUO_H
#define JIEGUO_H
/**************************类型定义**************************/
#include "3_大数.h"
typedef struct jd {
DASHU hds; //花朵数
struct jd *xyg; //下一个
}
JIEDIAN;
#include "常用.h"
/**************************函数原型**************************/
extern void jilu( DASHU * );
#include "3_大数.h" //xiaoyu()
#include <stdlib.h> //malloc(),NULL
#endif // JIEGUO_H
/*3_大数.h*/
#ifndef DASHU_H
#define DASHU_H
#include "0_问题.h" //DASHU用到了WEISHU
/**************************类型定义**************************/
//gw_sz[0]为个位,gw_sz[WEISHU-1]为最高位
//gw_sz[WEISHU-1]的值大于等于JINZHI表示溢出
typedef struct {
int gw_sz[WEISHU] ;
}
DASHU ;
#include "常用.h"
/**************************函数原型**************************/
extern void ds_fuzhi ( DASHU * const , const int ) ;
extern void ds_shuchu( const DASHU * const ) ;
extern void ds_jiaru ( DASHU * const , const DASHU * const ) ;
extern void ds_chengyi( DASHU * const , const int );
extern SF chaoguo_W(const DASHU * const);
extern SF buzu_W(const DASHU * const);
extern void qiu_sz_gs( int (*)[JINZHI] , const DASHU * const ) ;
extern SF xiaoyu ( const DASHU * const, const DASHU * const) ;
#endif // DASHU_H
->在"3_大数.c"中给出函数定义:
extern SF xiaoyu ( const DASHU * const p_ds1, const DASHU * const p_ds2)
{
int *t1 = p_ds1-> gw_sz , * w1 = t1 + WEISHU -1 ;
int *t2 = p_ds2-> gw_sz , * w2 = t2 + WEISHU -1 ;
while( w1 > t1 ){
if( *w1 < * w2){
return SHI ;
}
if( *w1-- > * w2-- ){
return FOU ;
}
}
if(*w1<*w2){
return SHI ;
}
return FOU ;
}
之后在main()中组织测试
#ifdef CESHI //测试
int main( void )
{
#define TEST_xiaoyu
#ifdef TEST_xiaoyu
#include "3_大数.h"
{
DASHU t1,t2 ;
ds_fuzhi(&t1,234);
ds_fuzhi(&t2,567);
printf("%d\n",xiaoyu(&t1,&t2)==SHI);
}
#endif
//……前面进行的其他测试(略)
system("PAUSE");
return 0;
}
#endif //CESHI
测试通过。至此,由qiongju()函数引出的全部函数完成。
22.输出结果
回到main()完成“//输出”部分
shuchu();//extern void shuchu(void);
依照下面次序
在本地写出函数调用—>在本地写函数原型—>将函数原型移动到"1_MAIN.h"
#ifdef QIUJIE //求解
int main( void )
{
//求解:穷举<=>验算<=>记录结果
qiongju();
//输出
shuchu();//extern void shuchu(void);
system("PAUSE");
return 0;
}
#endif //QIUJIE
->在"1_MAIN.h"中加上
#include "4_结果.h"
,之后将函数原型移动到"4_结果.h"
/*1_MAIN.h*/
#ifndef MAIN_H
#define MAIN_H
/**************************类型定义**************************/
/**************************函数原型**************************/
#include <stdlib.h> //system()
#include "2_穷举.h" //qiongju()
#include "4_结果.h"
#endif // MAIN_H
/*4_结果.h*/
#ifndef JIEGUO_H
#define JIEGUO_H
/**************************类型定义**************************/
#include "3_大数.h"
typedef struct jd {
DASHU hds; //花朵数
struct jd *xyg; //下一个
}
JIEDIAN;
#include "常用.h"
/**************************函数原型**************************/
extern void jilu( DASHU * );
#include "3_大数.h"
#include <stdlib.h> //malloc(),NULL
extern void shuchu(void);
#endif // JIEGUO_H
->在"4_结果.c"中给出函数定义
extern void shuchu(void)
{
while(tou!=NULL){
JIEDIAN *p_xyg = tou-> xyg ;
ds_shuchu(&tou->hds);
free( tou );
tou = p_xyg ;
}
tou = NULL ;
}
本以为一切都写完了,直接把"0_问题.h"中的
#define CESHI 改成了 #define QIUJIE
兴高采烈地编译运行,结果……发生了可怕的错误。
后经过仔细检查,发现错误出在extern void jilu( DASHU *p_ds )中
while ( *p_t != NULL
|| ( xiaoyu(&(*p_t)->hds , p_ds ) == SHI )
实际上却应为
while ( *p_t != NULL
&& ( xiaoyu(&(*p_t)->hds , p_ds ) == SHI )
教训就是,前面对这个函数测试的不充分。在完成xiaoyu()函数前,测试了加入一个节点的情形,完成xiaoyu()函数之后,本应再测试一次 jilu()函数,但由于完成在即,心存侥幸地偷懒了。
修正这个BUG之后,编译运行,程序的运行结果为
128468643043731391252
449177399146038697307
运行时间约10秒。