zoukankan      html  css  js  c++  java
  • 【算法】算法的艺术(六)

    报数游戏

       n个小孩围成一圈,从1开始报数,报到k的人退出,其余人重新从1报数,仍是报到k退出,直到圈中只剩m个小孩,问最后剩下的是哪些人?
      实例解析:
      本题在这里将借助于数组求解,用链表求解的方法放在第17章算法与数据结构实例中。
      设计思路:用数组元素模拟小孩。定义一个数组,每个元素存入一个数值作为小孩的编号,然后从第一个元素开始报数,报到k的人将编号清0,表示已退出圈子。在报数的过程中,凡是编号为0的人不再参加报数。当数组所有元素都报数后,重新从数组头开始报数,周而复始,直到圈中只剩m个小孩。
    #define N 100
      int main()
      {int a[N], n, m, k;
       int i, count, j;
       scanf(“%d%d%d”, &n, &k, &m);
       for(i = 1; i <= n; i++)
         a[i] = i;
       j = n;                         //j:圈中剩余小孩数
       count = 0;                    //为报数做准备,以便第一个小孩报1
       i = 1;                        //从数组的1号元素开始报数       
       while(j > m){
         if(a[i] != 0){             //若小孩未退出圈子
           count++;                  //参加报数
           if(count == k){          //若报到k
             a[i] = 0;               //退出圈子
          count = 0;              //清零,以便重新从1开始报数
             j--;                     //剩余人数减1
           }  
         }
        i++;                         //下一个小孩准备报数
         if(i > n)                   //若越过最后小孩
           i = 1;                    //转到第一个小孩
       }
       for(i = 1; i <= n; i++)
        if(a[i] != 0)
          printf(“%4d”, a[i]);
       getch();
       return 0;
      }
     
     
     

    时钟程序
       编写一个程序,显示系统时间,包括小时、分、秒,以及上下午,每秒刷新一次。
      实例解析:
      本实例需要用到与系统时间有关的一些函数。为方便程序员使用,Turbo C在dos.h中,定义了两个结构体,专门用于时间和日期处理:
    struct time{
        unsigned char ti_min;    //分
        unsigned char ti_hour;   //小时
       unsigned char ti_hund;   //百分秒
       unsigned char ti_sec;    //秒
      };
      struct date{
        int da_year;           //自1900年以来的年数
        char da_day;          //天数
        char da_mon;         //月数
      };
     
     
      Turbo C还在time.h中提供了一些与时间有关的函数:
      (1)char *ctime(const time_t *clock);
      作用:把clock所指的时间换成如下格式的字符串:Mon Nov 21 11:31:54  2009 。最后两个字符是换行符和空字符。
      (2)char *asctime(const struct tm *t);
      作用:把t所指的时间换成如下格式的字符串:Mon Nov 21 11:31:54  2009 。
      (3)double difftime(time_t time2, time_t time1);
      作用:返回两个时间的差,单位:秒。
       (4)struct tm *localtime(long *clock);
      作用:把clock所指时间转换为当地标准时间并以tm结构指针的形式返回。
    long time(long *p);
       作用:给出自1970年1月1日凌晨至今经过的秒数,并将该值写入p所指变量中。
    int stime(long *p);
       作用:将p所指时间写入计算机中。
     
       而在dos.h中提供了以下与时间有关的函数:
    void gettime(struct time *timep);
       作用:将计算机系统内的时间写入timep所指结构体变量中。
    settime(struct time *timep);
       作用:将系统时间设为timep所指的时间。
       本例中只用到函数gettime()。
       程序代码:
    #include <dos.h>
    #include <conio.h>
    int main()
    {struct time curtime;
     float cur_hour, cur_min, cur_sec;
     clrscr();
     do{
       printf("The current time is:
    ");
       gettime(&curtime);            //得到当前时间
       if(curtime.ti_hour <= 12)
         printf("AM ");
       else{
         printf("PM ");
         curtime.ti_hour -= 12;
       }
       if(curtime.ti_hour < 10)
         printf("0");
       printf("%d:", curtime.ti_hour);
       if(curtime.ti_min < 10)
         printf("0");
       printf("%d:", curtime.ti_min);
       if(curtime.ti_sec < 10)
         printf("0");
       printf("%d", curtime.ti_sec);
       sleep(1);                    //需要conio.h头文件
       clrscr();
     }while(!kbhit());
     return 0;
    }
     
     

    简单的计算器(一)
       编程,用来计算用户输入的四则运算表达式的值,只含加减乘除,不含括号。
      实例解析:
      表达式中含有加减乘除,乘除的优先级别比加减高。
      我们以键盘输入-3.12 + 2*3.5/4 + 8/2 - 3*6为例来说明算法。
      式子中的2*3.5/4、8/2和3*6要先算,算完之后整个表达式将只有4个数据项,剩下的问题就很简单了。为此我们可以把整个表达式分成4部分(4块),块与块之间必定是由加减号连接的,每块中间只有乘除,没有加减。
      实际上,没有必要先把每块的值都计算出来,在计算表达式的过程中,每遇到一块,可以先把这一块的结果算出来,然后与前面的计算结果进行加减运算,后面块的值可以在用到的时候再计算。
      具体的计算方法是:
      程序开始先定义一个变量result,并初始化为0。
      从头开始处理每一块:提取一个数据,如果数据后面是乘(除),则表示该块计算未结束,继续提取第二个数据并与第一个数据进行乘(除)运算,然后再看后面的运算符,如果还是’*’或’/’,则继续提取数据并进行计算……直到遇到运算符‘+’、‘-’或空字符为止。
      遇到运算符‘+’、‘-’或空字符,都表示该块的计算已经结束,可以将计算结果累加到result中了。
      重复上面的方法,对每一块都作这样的处理,直到表达式结束。result就是最后的结果。
    程序代码:
    #include "stdio.h"
      #include "stdlib.h"
      float get_num(char **);             
      int main()
      {char a[80];
       int sign = 1;      //对于表达式中的 ‘+’,sign = 1,对于‘-’,sign = -1
       float result = 0;
       char *p;            //用来指向要处理的字符
       clrscr();
       gets(a);
       p = a;
       if(*p == '-') {     //表达式第一个字符若是‘-’
          sign = -1;        //存储符号
          p++;        
       }
       while(*p != 0) {           //没有遇到空字符,则循环
          float  m;                //m用来存储某块的计算结果
        m = sign*get_num(&p);   //get_num执行过程中,p会向后移动
          while( *p == '*' || *p == '/' ){ //该循环求解某块的结果
             if( *p == '*' ) {
             p++;
             m *= get_num(&p);
           }
             else {
              int div;
           p++;
              div = get_num(&p);
              if( div == 0 ) {
             printf("错误!除数为0!
    ");
                 exit(1);
              }
              else
                 m /= div;
           }
          }
          if(*p != '+' && *p != '-' && *p != 0){
             printf("错误!遇到非法字符:%c
    ", *p);
             exit(0);
          }
          result += m;    //将上面计算出的某块的结果累加到result中
          if(*p == '+'){
             sign = 1;
             p++;
          }
          else if(*p == '-') {
             sign = -1;
             p++;
          }
          else          //遇到空字符,退出循环
            break;
         }
       printf("The result is %f
    ", result);
       getch();
       return 0;
      }
      float get_num(char **pp)    //pp指向p
      {float x = 0, m = 10;
       if(**pp != '.' && (**pp <'0' || **pp >'9') ) {
          printf("错误!运算符后面不是一个有效的数据
    ");
          exit(1);
       }
       while(**pp >= '0' && **pp <= '9') {
        x = x*10 + **pp - 48;
          (*pp)++;
       }
       if(**pp == '.') {
          (*pp)++;
          while(**pp >= '0' && **pp <= '9') {
             x += (**pp - 48)/m;
             (*pp)++;
             m *= 10;
          }
       }
       return x;
      }
     
     

    简单的计算器(二)
       编程,用来计算用户输入的四则运算表达式的值,含加减乘除和括号。
      实例解析:
      本实例与上例的区别在于表达式中有括号。其实每个括号中的内容都可以看作是一个单独的表达式(也可能又带括号),考虑到这一点,我们可以把程序写为递归调用的方式,遇到括号则调用自己计算括号中表达式的值。相应的程序代码如下:
    #include "stdio.h"
      #include "stdlib.h"
      float get_num(char **);
      float calculate(char **);
      int main()
      {char a[80];
       float result;
       char *p;
       clrscr();
       gets(a);
       p = a;
       result = calculate(&p);
       printf("%f
    ", result);
       getch();
       return 0;
      }
      float calculate(char **p)
      {float result = 0;
       int sign = 1;
       if(**p == '-') {
          sign = -1;
          (*p)++;
       }
       while(**p != 0 && **p != ')' ) {
         float  m;
         if(**p == '(' ) {
            (*p)++;
            m = sign*calculate(p);  //遇到括号调用自己计算括号中的值
         }
         else
            m = sign*get_num(p);
         while(**p == '*' || **p == '/') {
           if(**p == '*') {
           (*p)++;
           if(**p == '(') {
              (*p)++;
              m *= calculate(p);  //遇到括号调用自己计算括号中的值
           }
           else
             m *= get_num(p);
         }
           else {     
           int div;
           (*p)++;
           if(**p == '(') {
             (*p)++;
             div = calculate(p); //遇到括号调用自己计算括号中的值
           }
           else
             div = get_num(p);
           if(div == 0) {
              printf("diveide by 0!
    ");
              exit(1);
           }
           else
              m /= div;
         }
         }
         if(**p != '+' && **p != '-' && **p != 0 && **p != ')'){
             printf("illege character: %c
    ",**p);
             exit(0);
         }
         result += m;
         if(**p == '+') {
            sign = 1;
            (*p)++;
         }
         else
           if(**p == '-' ) {
           sign = -1;
           (*p)++;
         }
           else
           if(**p == ')' ) { //遇到右括号,跳过并退出循环返回结果
              (*p)++;
              break;
           }
           else
              break;
       }
       return result;
      }
      float get_num(char **p)
      {float n = 0, m = 10;
       if(**p != '.' && (**p <'0' || **p >'9')) {
          printf("get num error!
    ");
          exit(1);
       }
       while(**p >= '0' && **p <= '9') {
          n = n*10 + **p - 48;
          (*p)++;
       }
       if(**p == '.') {
          (*p)++;
          while(**p >= '0' && **p <= '9') {
             n += (**p - 48)/m;
             (*p)++;
             m *= 10;
          }
       }
       return n;
      }
     
     
     
     

    本文出自 “成鹏致远” 博客,请务必保留此出处http://infohacker.blog.51cto.com/6751239/1171349

  • 相关阅读:
    ECS:Systems
    ECS:Components
    ECS:Entitias
    对List遍历过程中添加和删除的思考
    SpringBoot 推荐博客
    理解和解决Java并发修改异常ConcurrentModificationException(转载)
    我对CopyOnWrite的思考
    最简日志打印规范(推荐,转载)
    为什么不应该使用Zookeeper做服务发现?(转载)
    浏览器允许跨域设置(不用于生产环境,开发用)
  • 原文地址:https://www.cnblogs.com/lcw/p/3159449.html
Copyright © 2011-2022 走看看