一、简介

本程序的思想和算法来自于C语言教材后的实训项目,程序通过用户输入四个整数计算出能够通过加减乘除得到数字24的所有表达式,程序的设计有别于一般通过穷举实现的方式,效率得到提高。算法介绍如下:

如用户输入1,2,3,4四个数字,先将其看成四个集合即{1},{2},{3},{4},整个叫做第一集群,后通过任意两个集合加减乘除{1,2},{1,3},{1,4},{2,3},{2,4},{3,4}六个集合叫做第二集群,而第三集群由第一集群和第二集群产生,而第四集群可由第一集群和第三集群以及由第二集群自身产生,最后比较第四集群所得到的的值是否24,输出结果


二、程序流程如下:

  1. 程序调用input函数处理用户输入,并同时生成四个相应的集合
  2. 调用函数calc,通过其中的list_cross函数产生第二、三、四集群
  3. 调用函数output输出,并同时删除相同的表达式
  4. 删除所有集群所占的空间,程序结束

三、主要的数据结构以及算法

为了提高计算精度,使用分数表示每一次计算结果

分数的结构 FRACTION

  1. typedef struct{
  2. int num;//分子
  3. int den;//分母
  4. }FRACTION; //注意分数的符号放在分子上

集群链表节点 s_ item

  1. typedef char EXPRESS[]; //存储具体的表达式,如2*3
  2. typedef struct s_item{
  3. FRACTION value; //集合的值 如expr为2*3,value.num=6,value.den=1
  4. EXPRESS expr; //表达式
  5. int flag[]; //每一个元素代表是否使用相应的数字,如用户输入了1,2,3,4,flag{1,1,0,0},表示
  6. //集合含有数字1和2
  7. struct s_item* next; //指向下一节点
  8. }ITEM,*PITEM;

主要的算法

分数的四则运算:

1.声明

  1. int commonDivisor(int a,int b);//最大公约数
  2. int commonMultiple(int a,int b);//最小公倍数
  3. //公倍数和公约数用于化简和计算分数
  4.  
  5. FRACTION plus(FRACTION a,FRACTION b);//分数的加法
  6. FRACTION sub(FRACTION a,FRACTION b);//分数的减法
  7. FRACTION multiple(FRACTION a,FRACTION b);//分数乘法
  8. FRACTION division(FRACTION a,FRACTION b);//分数的除法

2.定义

  1. //最大公约数
  2. int commonDivisor(int a,int b){
  3. int temp=;
  4. while(b!=){
  5. temp=a%b;
  6. a=b;
  7. b=temp;
  8. }
  9. return a;
  10. }
  11.  
  12. //最小公倍数
  13. int commonMultiple(int a,int b){
  14. return a*b/commonDivisor(a,b);
  15. }
  16.  
  17. //分数的加法
  18. FRACTION plus(FRACTION a,FRACTION b){
  19.  
  20. if(a.den==b.den){ //分母相同
  21.  
  22. a.num=a.num+b.num;
  23. }else{
  24. int cm=commonMultiple(a.den,b.den);
  25. a.num=a.num*(cm/a.den)+b.num*(cm/b.den);
  26. a.den=cm;
  27. }
  28.  
  29. //简化a,分子分母同除公约数
  30. int cm= commonDivisor(abs(a.num),a.den);
  31. a.num/=cm;
  32. a.den/=cm;
  33.  
  34. return a;
  35. }
  36.  
  37. //分数减法
  38. FRACTION sub(FRACTION a,FRACTION b){
  39.  
  40. if(a.den==b.den){ //分母相同
  41.  
  42. a.num=a.num-b.num;
  43. }else{
  44. int cm=commonMultiple(a.den,b.den);
  45. a.num=a.num*(cm/a.den)-b.num*(cm/b.den);
  46. a.den=cm;
  47. }
  48. //简化a,分子分母同除公约数
  49. int cm= commonDivisor(abs(a.num),a.den);
  50. a.num/=cm;
  51. a.den/=cm;
  52.  
  53. return a;
  54. }
  55.  
  56. //分数乘法
  57. FRACTION multiple(FRACTION a,FRACTION b){
  58.  
  59. a.num*=b.num;
  60. a.den*=b.den;
  61.  
  62. int cm= commonDivisor(abs(a.num),a.den);
  63. a.num/=cm;
  64. a.den/=cm;
  65.  
  66. return a;
  67. }
  68.  
  69. //分数的除法
  70. FRACTION division(FRACTION a,FRACTION b){
  71. int temp;
  72. if(b.num==){
  73. a.num=;
  74. a.den=;
  75. return a;//不能除0 ,返回分子,分母为0,作为标志
  76. }else if(b.num>){
  77. temp=b.num;
  78. b.num=b.den;
  79. b.den=temp;
  80. }else{
  81. temp =abs(b.num);
  82. b.num=b.den;
  83. b.den=temp;
  84. b.num*=-;
  85. }
  86. return multiple(a,b);
  87. }

集合之间的加减乘除产生新集合

1.声明

  1. PITEM add(PITEM a,PITEM b); //两个相加
  2. PITEM divide(PITEM a,PITEM b); //两个相除
  3. PITEM mutiply(PITEM a,PITEM b); //两个相乘
  4. PITEM subtract(PITEM a,PITEM b); //两个相减

2.定义

  1. PITEM add(PITEM a,PITEM b) //两个相加
  2. {
  3.  
  4. PITEM x=(struct s_item*)malloc(sizeof(struct s_item));
  5. x->value=plus(a->value,b->value);
  6.  
  7. int m;
  8. for(m=;m<;m++){
  9. x->flag[m]=;
  10. }
  11.  
  12. int k=;
  13. x->expr[k]='(';
  14. int j;
  15. for(j=;a->expr[j]!='\0';j++){
  16. x->expr[++k]=a->expr[j];
  17. }
  18. x->expr[++k]='+';
  19. for(j=;b->expr[j]!='\0';j++){
  20. x->expr[++k]=b->expr[j];
  21. }
  22. x->expr[++k]=')';
  23. x->expr[++k]='\0';
  24.  
  25. int i=;
  26. for(i=;i<;i++){
  27. if(a->flag[i]==){
  28. x->flag[i]=;
  29. }
  30.  
  31. if(b->flag[i]==){
  32. x->flag[i]=;
  33. }
  34.  
  35. }
  36.  
  37. x->next=NULL;
  38.  
  39. return x;
  40. }
  41.  
  42. PITEM divide(PITEM a,PITEM b){ //集合相除
  43. PITEM x=(struct s_item*)malloc(sizeof(struct s_item));
  44. x->value=division(a->value,b->value);
  45.  
  46. int m;
  47. for(m=;m<;m++){
  48. x->flag[m]=;
  49. }
  50. if(x->value.num==&&x->value.den==){
  51. free(x);
  52. return NULL;
  53. }
  54.  
  55. int k=;
  56. x->expr[k]='(';
  57. int j;
  58. for(j=;a->expr[j]!='\0';j++){
  59. x->expr[++k]=a->expr[j];
  60. }
  61. x->expr[++k]='/';
  62. for(j=;b->expr[j]!='\0';j++){
  63. x->expr[++k]=b->expr[j];
  64. }
  65. x->expr[++k]=')';
  66. x->expr[++k]='\0';
  67.  
  68. int i=;
  69. for(i=;i<;i++){
  70. if(a->flag[i]==){
  71. x->flag[i]=;
  72. }
  73.  
  74. if(b->flag[i]==){
  75. x->flag[i]=;
  76. }
  77.  
  78. }
  79.  
  80. x->next=NULL;
  81. return x;
  82. }
  83. PITEM mutiply(PITEM a,PITEM b)//两个相乘
  84. {
  85. PITEM x=(struct s_item*)malloc(sizeof(struct s_item));
  86. x->value=multiple(a->value,b->value);
  87. int m;
  88. for(m=;m<;m++){
  89. x->flag[m]=;
  90. }
  91. int k=;
  92. x->expr[k]='(';
  93. int j;
  94. for(j=;a->expr[j]!='\0';j++){
  95. x->expr[++k]=a->expr[j];
  96. }
  97. x->expr[++k]='*';
  98. for(j=;b->expr[j]!='\0';j++){
  99. x->expr[++k]=b->expr[j];
  100. }
  101. x->expr[++k]=')';
  102. x->expr[++k]='\0';
  103.  
  104. int i=;
  105. for(i=;i<;i++){
  106. if(a->flag[i]==){
  107. x->flag[i]=;
  108. }
  109.  
  110. if(b->flag[i]==){
  111. x->flag[i]=;
  112. }
  113.  
  114. }
  115.  
  116. x->next=NULL;
  117. return x;
  118. }
  119.  
  120. PITEM subtract(PITEM a,PITEM b){ //相减
  121. PITEM x=(struct s_item*)malloc(sizeof(struct s_item));
  122. x->value=sub(a->value,b->value);
  123. int m;
  124. for(m=;m<;m++){
  125. x->flag[m]=;
  126. }
  127. int k=;
  128. x->expr[k]='(';
  129. int j;
  130. for(j=;a->expr[j]!='\0';j++){
  131. x->expr[++k]=a->expr[j];
  132. }
  133. x->expr[++k]='-';
  134. for(j=;b->expr[j]!='\0';j++){
  135. x->expr[++k]=b->expr[j];
  136. }
  137. x->expr[++k]=')';
  138. x->expr[++k]='\0';
  139.  
  140. int i=;
  141. for(i=;i<;i++){
  142. if(a->flag[i]==){
  143. x->flag[i]=;
  144. }
  145.  
  146. if(b->flag[i]==){
  147. x->flag[i]=;
  148. }
  149.  
  150. }
  151.  
  152. x->next=NULL;
  153. return x;
  154. }

核心代码

产生新集群 list_cross

  1. //比较集群之间是否有相同数字
  2. int cmp(PITEM left,PITEM right){
  3. int i;
  4. for(i=;i<;i++){
  5. if(left->flag[i]==&&right->flag[i]==){
  6. return ;
  7. }
  8. }
  9. return ;
  10. }
  11.  
  12. //结合两个集群产生下一个集群
  13. void list_cross(PITEM left,PITEM right,PITEM result){
  14.  
  15. PITEM p,q;
  16. for(p=left->next;p!=NULL;p=p->next){ //循环调用两个集群中所有集合
  17. for(q=right->next;q!=NULL;q=q->next)
  18. if(cmp(p,q)==){ //只有两集合不含相同数字才运算
  19. PITEM temp=NULL;
  20. if((temp=add(p,q))!=NULL){
  21. temp->next=result->next;
  22. result->next=temp;
  23. }
  24. if((temp=subtract(p,q))!=NULL){
  25. temp->next=result->next;
  26. result->next=temp;
  27. }
  28. if((temp=divide(p,q))!=NULL){
  29. temp->next=result->next;
  30. result->next=temp;
  31. }
  32. if((temp=mutiply(p,q))!=NULL){
  33. temp->next=result->next;
  34. result->next=temp;
  35. }
  36.  
  37. }
  38. }
  39. }

因为用户有可能输入相同的数字,所以要消除相同的表达式:

消除重复表达式

  1. PITEM p=p4_head->next; //p指向第四集群的头结点,第四集群即最后四个数字都已经使用的集合
  2.  
  3. //消除重复的表达式
  4.  
  5. PITEM q,pre;
  6. for(;p!=NULL;p=p->next){
  7. for(q=p->next,pre=p;q!=NULL;){
  8. if(strcmp(p->expr,q->expr)==){
  9.  
  10. pre->next=q->next;
  11. PITEM temp=q; //pre为p的前一个节点
  12. q=q->next;
  13.  
  14. free(temp);//消失重复点;
  15. temp=NULL;
  16.  
  17. }else{
  18. q=q->next;
  19. pre=pre->next;
  20. }
  21. }
  22. }

判断集合的值,输出结果

  1. //输出
  2. p=p4_head->next;
  3. while(p!=NULL){
  4. if(p->value.num==&&p->value.den==){
  5.  
  6. puts(p->expr);
  7.  
  8. }
  9.  
  10. p=p->next;
  11. }

四、运行

               

源代码地址:C语言实现24点src

C语言实现24点程序的更多相关文章

  1. C语言学习书籍推荐《学通C语言的24堂课》下载

    下载地址:点我 编辑推荐 <学通C语言的24堂课>:用持续激励培养良好习惯以良好习惯铸就伟大梦想——致亲爱的读者朋友在开始学习<学通C语言的24堂课>的同时,强烈建议读者朋友同 ...

  2. C语言之简易了解程序环境

    C语言之简易了解程序环境 大纲: 程序的翻译环境 预编译 编译 汇编 链接 程序的运行环境 在ANSI C的任何一种实现中,存在两个不同的环境. 第1种是翻译环境,在这个环境中源代码被转换为可执行的机 ...

  3. 基于php基础语言编写的小程序之计算器

    基于php基础语言编写的小程序之计算器 需求:在输入框中输入数字进行加.减.乘.除运算(html+php) 思路: 1首先要创建输入数字和运算符的输入框,数字用input的text属性,运算符用sel ...

  4. 利用Scala语言开发Spark应用程序

    Spark内核是由Scala语言开发的,因此使用Scala语言开发Spark应用程序是自然而然的事情.如果你对Scala语言还不太熟悉,可 以阅读网络教程A Scala Tutorial for Ja ...

  5. SAS进阶《深入解析SAS》之开发多语言支持的SAS程序

    SAS进阶<深入解析SAS>之开发多语言支持的SAS程序 1. 多语言支持的应用程序是指该程序在世界给第使用时,其能够处理的数据,以及处理数据的方式.信息展现的方式都符合当地的语言.文化习 ...

  6. JAVA 基础编程练习题24 【程序 24 根据输入求输出】

    24 [程序 24 根据输入求输出] 题目:给一个不多于 5 位的正整数,要求:一.求它是几位数,二.逆序打印出各位数字. package cskaoyan; public class cskaoya ...

  7. [转载] 使用C/C++语言编写基于DSP程序的注意事项

    原文地址:『转』使用C/C++语言编写基于DSP程序的注意事项作者:skysmile   1.不影响执行速度的情况下,可以使用c或c/c++语言提供的函数库,也可以自己设计函数,这样更易于使用“裁缝师 ...

  8. 程序员之---C语言细节24(段错误、类型提升、sizeof &#39;A&#39;)

    主要内容:段错误.类型提升.sizeof  'A' #include <stdio.h> int main() { union test{ char a[10]; int b; }u; i ...

  9. 平方根的C语言实现(三) ——最终程序实现

    版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/7223254.html 作者:窗户 Q ...

随机推荐

  1. Python网络爬虫-xpath模块

    一.正解解析 单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 \d :数字 [0-9] \D : 非数字 \w :数字.字母.下划线.中文 \W : 非\ ...

  2. bzoj 4911: [Sdoi2017]切树游戏

    考虑维护原树的lct,在上面dp,由于dp方程特殊,均为异或卷积或加法,计算中可以只使用fwt后的序列 v[w]表示联通子树的最浅点为w,且不选w的splay子树中的点 l[w]表示联通子树的最浅点在 ...

  3. 错误:Unsupported major.minor version 51.0(jdk版本错误)

    Java.lang.UnsupportedClassVersionError: org/apache/nutch/crawl/Crawl3 : Unsupported major.minor vers ...

  4. 牛客网暑期ACM多校训练营(第七场)J题(Sudoku Subrectangles)题解

    一.题意 给定一个高度为$n$,宽度为$m$的字母矩形(有大写和小写字母,共$52$种),问里面有多少个子矩形是“数独矩形”.数独矩形是指,该矩形内每一行内元素都不相同,每一列内元素也不相同. 二.思 ...

  5. Docker集群管理(二)—— docker+swarm+etcd+shipyard

    引言 前一篇介绍如何简单的搭建一个可视化管理的docker集群,本篇将在此基础之上引入etcd发现服务. 目的 使用etcd发现服务解决swarm内置发现服务的不稳定问题.etcd采用raft算法,这 ...

  6. 链接mysql的两种方法

    使用mysql二进制方式连接 您可以使用MySQL二进制方式进入到mysql命令提示符下来连接MySQL数据库. 实例 以下是从命令行中连接mysql服务器的简单实例: [root@host]# my ...

  7. storm的优化以及雪崩问题

    下图来说明什么是雪崩现象: 当spout发送的速度非常快,而bolt的处理速度很慢,spout源源不断地向内存中发送tuple,这样下去迟早会把内存撑爆,这样就叫做雪崩现象! 怎么处理雪崩问题呢 第一 ...

  8. Linux入门之vi

    How to Use the vi Editor* *Copyright 1991 by Simon Fraser University. Reprinted with permission. The ...

  9. java技术-重点方向

    多线程 锁 事务 缓存 hashmap 并发编程

  10. 15.python操作mysql

    导入包 from pymysql import* 1. 创建 Connection 连接 conn=conne(host='192.168.13.130',port=3306 ,database='' ...