C语言经典算法学习-4

文章目录

    • 21.最大访客数
    • 22.中序式转后序式(前序式)
    • 23.后序式的运算
    • 24.洗扑克牌(乱数排列)
    • 25.Craps赌博游戏

21.最大访客数

说明:现将举行一个餐会,让访客事先填写到达时间与离开时间,为了掌握座位的数目,必须先估计不同时间的最大访客数。
解法:这个题目看似有些复杂,其实相当简单,单就计算访客数这个目的,同时考虑同一访客的来访时间与离开时间,反而会使程式变得复杂;只要将来访时间与离开时间分开处理就可以了,假设访客 i 的来访时间为x[i],而离开时间为y[i]。

在资料输入完毕之后,将x[i]与y[i]分别进行排序(由小到大),道理很简单,只要先计算某时之前总共来访了多少访客,然后再减去某时之前的离开访客,就可以轻易的解出这个问题。

#include <stdio.h> 
#include <stdlib.h> 
#define MAX 100 
#define SWAP(x,y) {int t; t = x; x = y; y = t;} int partition(int[], int, int); 
void quicksort(int[], int, int); // 快速排序法
int maxguest(int[], int[], int, int); int main(void) { int x[MAX] = {0}; int y[MAX] = {0}; int time = 0; int count = 0; printf("\n输入来访与离开125;时间(0~24):"); printf("\n范例:10 15"); printf("\n输入-1 -1结束"); while(count < MAX) { printf("\n>>"); scanf("%d %d", &x[count], &y[count]); if(x[count] < 0) break; count++; } if(count >= MAX) { printf("\n超出最大访客数(%d)", MAX); count--; } // 预先排序 quicksort(x, 0, count); quicksort(y, 0, count); while(time < 25) { printf("\n%d 时的最大访客数:%d", time, maxguest(x, y, count, time)); time++; } printf("\n"); return 0; 
} int maxguest(int x[], int y[], int count, int time) { int i, num = 0; for(i = 0; i <= count; i++) { if(time > x[i]) num++; if(time > y[i]) num--; } return num; 
} int partition(int number[], int left, int right) { int i, j, s; s = number[right]; i = left - 1; for(j = left; j < right; j++) { if(number[j] <= s) { i++; SWAP(number[i], number[j]); } } SWAP(number[i+1], number[right]); return i+1; 
} void quicksort(int number[], int left, int right) { int q; if(left < right) { q = partition(number, left, right); quicksort(number, left, q-1); quicksort(number, q+1, right); } 
} 

22.中序式转后序式(前序式)

说明平常所使用的运算式,主要是将运算元放在运算子的两旁,例如a+b/d这样的式子,这称之为中序(Infix)表示式,对于人类来说,这样的式子很容易理 解,但由于电脑执行指令时是有顺序的,遇到中序表示式时,无法直接进行运算,而必须进一步判断运算的先后顺序,所以必须将中序表示式转换为另一种表示方 法。

可以将中序表示式转换为后序(Postfix)表示式,后序表示式又称之为逆向波兰表示式(Reverse polish notation),它是由波兰的数学家卢卡谢维奇提出,例如(a+b)(c+d)这个式子,表示为后序表示式时是ab+cd+
解法用手算的方式来计算后序式相当的简单,将运算子两旁的运算元依先后顺序全括号起来,然后将所有的右括号取代为左边最接近的运算子(从最内层括号开始),最后去掉所有的左括号就可以完成后序表示式,例如:
a+bd+c/d => ((a+(bd))+(c/d)) -> bd*+cd/+

如果要用程式来进行中序转后序,则必须使用堆叠,演算法很简单,直接叙述的话就是使用回圈,取出中序式的字元,遇运算元直接输出,堆叠运算子与左括号, ISP>ICP的话直接输出堆叠中的运算子,遇右括号输出堆叠中的运算子至左括号。

在这里插入图片描述

如果要将中序式转为前序式,则在读取中序式时是由后往前读取,而左右括号的处理方式相反,其余不变,但输出之前必须先置入堆叠,待转换完成后再将堆叠中的 值由上往下读出,如此就是前序表示式。

#include <stdio.h> 
#include <stdlib.h> int postfix(char*); // 中序转后序 
int priority(char); // 决定运算子优先顺序 int main(void) { char input[80]; printf("输入中序运算式:"); scanf("%s", input); postfix(input); return 0; 
} int postfix(char* infix) { int i = 0, top = 0; char stack[80] = {'\0'}; char op; while(1) { op = infix[i]; switch(op) { case '\0': while(top > 0) { printf("%c", stack[top]); top--; } printf("\n"); return 0; // 运算子堆叠 case '(': if(top < (sizeof(stack) / sizeof(char))) { top++; stack[top] = op; } break; case '+': case '-': case '*': case '/': while(priority(stack[top]) >= priority(op)) { printf("%c", stack[top]); top--; } // 存入堆叠 if(top < (sizeof(stack) / sizeof(char))) { top++; stack[top] = op; } break; // 遇 ) 输出至 ( case ')': while(stack[top] != '(') { printf("%c", stack[top]); top--; } top--;  // 不输出( break; // 运算元直接输出 default: printf("%c", op); break; } i++; } 
} int priority(char op) { int p; switch(op) { case '+': case '-': p = 1; break; case '*': case '/': p = 2; break; default: p = 0; break; } return p; 
} 

23.后序式的运算

说明 将中序式转换为后序式的好处是,不用处理运算子先后顺序问题,只要依序由运算式由前往后读取即可。
解法
在这里插入图片描述

#include <stdio.h> 
#include <stdlib.h> void evalPf(char*); 
double cal(double, char, double); int main(void) { char input[80]; printf("输入后序式:"); scanf("%s", input); evalPf(input); return 0; 
} void evalPf(char* postfix) { double stack[80] = {0.0}; char temp[2]; char token; int top = 0, i = 0; temp[1] = '\0'; while(1) { token = postfix[i]; switch(token) { case '\0': printf("ans = %f\n", stack[top]); return; case '+': case '-': case '*': case '/': stack[top-1] = cal(stack[top], token, stack[top-1]); top--; break; default: if(top < sizeof(stack) / sizeof(float)) { temp[0] = postfix[i]; top++; stack[top] = atof(temp); } break; } i++; } 
} double cal(double p1, char op, double p2) { switch(op) { case '+': return p1 + p2; case '-': return p1 - p2; case '*': return p1 * p2; case '/': return p1 / p2; } 
} 

24.洗扑克牌(乱数排列)

说明
洗扑克牌的原理其实与乱数排列是相同的,都是将一组数字(例如1~N)打乱重新排列,只不过洗扑克牌多了一个花色判断的动作而已。
解法
初学者通常会直接想到,随机产生1~N的乱数并将之存入阵列中,后来产生的乱数存入阵列前必须先检查阵列中是否已有重复的数字,如果有这个数就不存入,再重新产生下一个数,运气不好的话,重复的次数就会很多,程式的执行速度就很慢了,这不是一个好方法。

以1~52的乱数排列为例好了,可以将阵列先依序由1到52填入,然后使用一个回圈走访阵列,并随机产生1~52的乱数,将产生的乱数当作索引取出阵列值,并与目前阵列走访到的值相交换,如此就不用担心乱数重复的问题了,阵列走访完毕后,所有的数字也就重新排列了。

至于如何判断花色?这只是除法的问题而已,取商数判断花色,取余数判断数字,您可以直接看程式比较清楚。
实作

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 52int main(void) {int poker[N + 1];int i, j, tmp, remain;// 初始化阵列 for(i = 1; i <= N; i++)poker[i] = i; srand(time(0));// 洗牌 for(i = 1; i <= N; i++) {j = rand() % 52 + 1;tmp = poker[i];poker[i] = poker[j]; poker[j] = tmp; }for(i = 1; i <= N; i++) {// 判断花色 switch((poker[i]-1) / 13) { case 0: printf("桃"); break;case 1: printf("心"); break;case 2: printf("砖"); break;case 3: printf("梅"); break;} // 扑克牌数字 remain = poker[i] % 13;switch(remain) { case 0: printf("K "); break;case 12: printf("Q "); break;case 11: printf("J "); break;default: printf("%d ", remain); break;} if(i % 13 == 0)printf("\n");} return 0;
} 

25.Craps赌博游戏

说明一个简单的赌博游戏,游戏规则如下:玩家掷两个骰子,点数为1到6,如果第一次点数和为7或11,则玩家胜,如果点数和为2、3或12,则玩家输,如果和 为其它点数,则记录第一次的点数和,然后继续掷骰,直至点数和等于第一次掷出的点数和,则玩家胜,如果在这之前掷出了点数和为7,则玩家输。
解法 规则看来有些复杂,但是其实只要使用switch配合if条件判断来撰写即可,小心不要弄错胜负顺序即可。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define WON 0
#define LOST 1
#define CONTINUE 2int rollDice() { return (rand() % 6) + (rand() % 6) + 2;
}int main(void) {int firstRoll = 1;int gameStatus = CONTINUE;int die1, die2, sumOfDice;int firstPoint = 0;char c;srand(time(0));printf("Craps赌博游戏,按Enter键开始游戏****");while(1) {getchar();if(firstRoll) {sumOfDice = rollDice();printf("\n玩家掷出点数和:%d\n", sumOfDice);switch(sumOfDice) {case 7: case 11:gameStatus = WON; break;case 2: case 3: case 12:gameStatus = LOST; break;default:firstRoll = 0;gameStatus = CONTINUE;firstPoint = sumOfDice;break;}}else {sumOfDice = rollDice();printf("\n玩家掷出点数和:%d\n", sumOfDice);if(sumOfDice == firstPoint)gameStatus = WON;else if(sumOfDice == 7)gameStatus = LOST;}if(gameStatus == CONTINUE)puts("未分胜负,再掷一次****\n");else {if(gameStatus == WON)puts("玩家胜");elseputs("玩家输");printf("再玩一次?");scanf("%c", &c);if(c == 'n') {puts("游戏结束");break;}firstRoll = 1;}}return 0;
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/535115.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新建项目module,但想归到一个目录下面

1. 想建几个module, 例如 component-base-service,component-config-service, 但是module多了会在CloudAction下面显示很多目录, 所以想把它们归到components模块下面去, 类似于下图的效果 2. 创建过程 右击CloudAction 新建 module -> 选maven类型 输入components, 建成后删…

Pytorch基础(21)-- torch.repeat_interleave()方法

分享一下自己目前在维护的Github项目&#xff0c;由于本人博士阶段接触了一个全新的研究方向-----使用机器学习、强化学习、深度学习等方法解决组合优化问题&#xff0c;维护这个项目的目的&#xff1a; &#xff08;1&#xff09;记录自己阅读过的paper&#xff0c;同时分享一…

浅谈如何自我实现一个消息队列服务器(1)——需求分析

文章目录 一、什么是消息队列&#xff1f;二、当下主流的消息队列(MQ)三、自我实现一个消息队列服务器的前期准备——需求分析3.1 核心概念3.2 broker server 核心概念3.2.1、虚拟主机&#xff08;Virtual Host&#xff09;3.2.2、交换机&#xff08;Exchange&#xff09;3.2.2…

外包干了5天,技术明显退步。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入南京某软件公司&#xff0c;干了接近2年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了2年的功能测试&…

BEC报考公告 ,柯桥成人学商务英语,商务英语口语学校

BEC报考公告 报名时间 2024年3月12日10:00——2023年3月20日10:00 注册个人信息、上传电子照片并支付考试费用 考试时间 BEC初级&#xff1a;5月12日 BEC中级&#xff1a;5月25日 BEC高级&#xff1a;5月18日 笔试及口试具体时间以准考证为准 报名费用 初级&#xff1a;…

C++矢量运算与java矢量运算

矢量运算 概述&#xff1a; 矢量运算是一种基于向量的数学运算&#xff0c;它遵循特定的法则。以下是矢量运算的一些基本原理&#xff1a; 矢量加法&#xff1a;可以使用平行四边形法则或三角形法则来执行。当两个矢量相加时&#xff0c;可以将它们的起点放在同一个点上&…

朴素贝叶斯算法基础——案例:对新闻进行分类

贝叶斯公式 朴素&#xff1a;假设特征与特征之间相互独立 朴素贝叶斯算法&#xff1a;朴素贝叶斯 应用场景&#xff1a;文本分类&#xff08;单词作为特征&#xff09; 拉普拉斯平滑系数 Ni&#xff1a;F1词在C类别所有文档中出现的次数 N&#xff1a;所属类别C下的文档所…

华为车控面试前后

个人经历&#xff1a; 秋招未接受其他公司offer&#xff0c;all in华子。 ->秋招失败0 offer 年前被车bu捞后入池开始审批。 ->等待超过1个月&#xff0c;陷入煎熬。 ->终于等到意向书。 分享时间线&#xff1a; 10月 笔试和3面入池2012 1月 收到车bu捞人电话解…

JVM是如何运行的

JVM&#xff08;Java Virtual Machine&#xff0c;Java虚拟机&#xff09;是 Java 程序的运行环境&#xff0c;它负责将 Java 字节码翻译成机器代码并执行。也就是说 Java 代码之所以能够运行&#xff0c;主要是依靠 JVM 来实现的。 JVM 整体的大概执行流程是这样的&#xff1…

尚硅谷SpringBoot3笔记

推荐课程&#xff1a;03.快速入门-示例Demo_哔哩哔哩_bilibili 官方笔记&#xff1a;SpringBoot3全栈指南 (yuque.com) 目录 01 -- 示例demo 1. 在新建项目创建一个Maven 模块 2. 引入 spring-boot-starter-parent 和 spring-boot-starter-web 依赖 3. 指示 Spring Boot 启…

Spring多线程事务处理

一、背景 本文主要介绍了spring多线程事务的解决方案&#xff0c;心急的小伙伴可以跳过上面的理论介绍分析部分直接看最终解决方案。 在我们日常的业务活动中&#xff0c;经常会出现大规模的修改插入操作&#xff0c;比如在3.0的活动赛事创建&#xff0c;涉及到十几张表的插入…

doris安装(docker方式)

背景 doris有两个进程 fe,处理用户请求,查询,元数据管理,节点管理be,数据存储,查询计划执行 架构图如下: 参考:https://doris.apache.org/zh-CN/docs/get-starting/what-is-apache-doris 1、定义docker-compose文件 version: 3 services:docker-fe:image: "apac…