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 52

int 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 2

int 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("玩家胜");
            else
                puts("玩家输");

            printf("再玩一次?");
            scanf("%c", &c);
            if(c == 'n') {
                puts("游戏结束");
                break;
            }
            firstRoll = 1;
        }
    }
    return 0;
} 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年Vue3 面试题小总结

Vue3 面试题小总结 1. OptionsAPI 与 CompositionAPI 的区别&#xff1f; OptionsAPI&#xff1a; 选项式API&#xff0c;通过定义data、computed、watch、method等属性与方法&#xff0c;共同处理页面逻辑&#xff1b;缺点&#xff1a; 当组件变得复杂的时候&#xff0c;导致…

视频分割软件,到底哪一款才适合你?

在当今充满创意的数字时代&#xff0c;视频编辑已成为许多人表达想法、分享故事的重要手段。而在视频编辑的过程中&#xff0c;分割视频是一项关键而常见的任务&#xff0c;它能够让我们更精细地处理内容&#xff0c;使得最终的作品更为生动和引人入胜。然而&#xff0c;要想高…

揭秘财务数据分析的五力分析,轻松实现从会计财务到管理财务的华丽转身

在这个信息爆炸的时代&#xff0c;财务数据分析已经成为了企业和个人成功的关键。今天&#xff0c;就让我们一起揭开财务数据分析的神秘面纱&#xff0c;让你轻松掌握财务秘籍&#xff0c;成为财务高手&#xff01; 一、财务数据分析&#xff0c;为何如此重要&#xff1f; 财…

访客到了官网就跳走,概率是官网颜值和体验出了问题。

很多小伙伴反馈官网ip不错&#xff0c;但是pv太少了&#xff0c;停留时间更少&#xff0c;这大概率是网站颜值和体验出问题了。 如果访客到了官网后就跳走&#xff0c;有可能是因为官网的颜值和用户体验出了问题。这种情况可能会导致访客对网站的第一印象不佳&#xff0c;从而选…

【spring】使用阿里Spring Initailiz创建项目

网络原因使用Spring Initailiz会出现超时。 那我们就换成阿里的 先看看spring官网的 网址&#xff1a;https://start.spring.io 使用一下阿里的 网址&#xff1a;https://start.aliyun.com/ 填写信息 都是java开发者&#xff0c;具体信息部介绍了。 选择组件 lombok spri…

OKHttpRetrofit

完成一个get请求 1.导入依赖 implementation("com.squareup.okhttp3:okhttp:3.14.")2.开启viewBinding android.buildFeatures.viewBinding true 3.加网络权限 和 http明文请求允许配置文件 <?xml version"1.0" encoding"utf-8"?> &l…

Kotlin:内联类(inline class)

点击查询内联类中文文档 点击查询内联类英文文档 简介 提醒&#xff1a;内联类仅在 Kotlin 1.3 之后版本可用 有时候&#xff0c;业务逻辑需要围绕某种类型创建包装器。然而&#xff0c;由于额外的堆内存分配问题&#xff0c;它会引入运行时的性能开销。此外&#xff0c;如果…

【嵌入式——QT】标准对话框

【嵌入式——QT】标准对话框 文件对话框颜色对话框字体对话框输入对话框消息框代码示例 文件对话框 QFileDialog 常用静态函数 getOpenFileName&#xff1a;选择打开一个文件&#xff1b;getOpenFileNames&#xff1a;选择打开多个文件&#xff1b;getSaveFileName&#xff1…

如何使用ArcGIS Pro生成带计曲线等高线

等高线作为常见的地图要素经常会被使用到&#xff0c;一般情况下生成的等高线是不带计曲线的&#xff0c;在某些情况下我们需要带计曲线的等高线&#xff0c;这里为大家介绍一下ArcGIS Pro生成带计曲线等高线的方法&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数…

13、设计模式之模板模式(Template)

一、什么是模板模式 模板模式是一种基于继承实现的设计模式&#xff0c;它是行为型的模式。 主要思想是将定义的算法抽象成一组步骤&#xff0c;在抽象类种定义算法的骨架&#xff0c;把具体的操作留给子类来实现。 通俗地说&#xff0c;模板模式就是将某一行为制定一个框架&…

vue3 实现一个tab切换组件

一. 效果图 二. 代码 文件 WqTab.vue: <template><div ref"wqTabs" class"wq-tab"><template v-for"tab in tabs" :key"tab"><div class"tab-item" :class"{ ac: tabActive tab.key }" c…

LeetCode102题:二叉树的层序遍历(python3)

代码思路&#xff1a;使用队列先进先出的特性&#xff0c;queue[]不为空进入for循环&#xff0c;tmp存储每层的节点&#xff0c;将结果添加至res[]中。 python中使用collections中的双端队列deque()&#xff0c;其popleft()方法可达到O(1)时间复杂度。 class Solution:def lev…

uni-app开发特点和开发流程

uni-app是一个基于Vue.js框架的跨平台应用开发框架&#xff0c;通过一套代码可以同时运行在多个平台上&#xff0c;包括iOS、Android、H5等。它采用了基于流布局的页面渲染机制&#xff0c;可以自动适配不同平台的屏幕尺寸和分辨率。uniapp官网&#xff1a;https://uniapp.dclo…

概率与常见的概率分布

概率是数据分析、机器学习中最基础的知识。也是在生活中最实用的一门学科&#xff0c;学了很多大道理不一定能过好一生&#xff0c;学好概率则有一定概率会变得更好。为大概率坚持&#xff0c;为小概率备份。 概率与分布 要想了解概率&#xff0c;首先得搞清楚概率和概率分布的…

2024蓝桥杯每日一题(区间合并)

一、第一题&#xff1a;挤牛奶 解题思路&#xff1a;区间合并 区间合并模板题 【Python程序代码】 n int(input()) a [] for i in range(n):l,r map(int,input().split())a.append([l,r]) def cmp(x):return x[0],x[1] a.sort(keycmp) res1,res20,0 st,ed a[0][0…

SQLiteC/C++接口详细介绍之sqlite3类(五)

快速跳转文章列表&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;四&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;六&#xff09;&#xff08;未发表&#xff09; 14.sqlite3_busy_handle…

猫咪挑食不吃猫粮是为什么?适口性好、普口性价的主食冻干推荐

现在咱养猫人个个吧自家的小猫咪当成宝贝宠着&#xff0c;宠着宠着一些坏习惯就出来。 然而&#xff0c;这种宠爱有时也会导致猫咪养成挑食的不良习惯。那么&#xff0c;当猫咪拒绝吃猫粮时&#xff0c;我们应该如何应对呢&#xff1f;今天跟大家一起来分析分析猫咪挑食不吃猫…

Claude3相较于GPT4有哪些优点?

Claude 最实在的一点是即使是普通用户&#xff0c;也能用到上传文件、上传图片这些功能&#xff08;只是用的模型比付费版性能差一些&#xff0c;对普通用户开放的是 Sonnet 版本&#xff0c;付费用户是 Opus 版本&#xff09;。 但是 ChatGPT 就不行&#xff0c;免费的 GPT-3…

唯众物联网+地理科学交付云南师范大学地理学部教学实验室项目

近日&#xff0c;云南师范大学地理学部教学实验室建设项目顺利交付。该项目的成功落地&#xff0c;标志着物联网技术与地理科学教育的深度融合&#xff0c;为云南师范大学的地理教学提供了全新的教学平台与资源。该项目以物联网技术为核心&#xff0c;结合地理科学的特点&#…

UI 学习 二 可访问性 模式

一 颜色对比 颜色和对比度可以用来帮助用户看到和理解应用程序的内容&#xff0c;与正确的元素交互&#xff0c;并理解操作。 颜色可以帮助传达情绪、语气和关键信息。可以选择主色、辅助色和强调色来支持可用性。元素之间足够的颜色对比可以帮助低视力的用户看到和使用你的应…