鱼C论坛

 找回密码
 立即注册
查看: 5139|回复: 5

[技术交流] 中缀转后缀(Infix2Postfix.c)

[复制链接]
发表于 2015-12-18 22:46:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 spy 于 2015-12-19 10:18 编辑
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <ctype.h>
#include <conio.h>
#include <math.h>

/*
算法的基本思想是:
        顺序扫描键盘缓冲区中输入的中缀表达式,读到操作数时,直接将其存放至操作数队列
        读到运算符时,将操作符栈中所有优先级高于或等于该运算符的运算符弹出栈,
        并将其存放至操作数队列,然后在将读入的运算符入栈
        当读入左括号时直接入栈;
        当读到右括号时,将与靠近栈顶的第一个左括号之间的运算符全部依次弹出栈,存放至输出队列
*/

struct StackNode
{
        char data;
        struct StackNode* next;
};
void Push(struct StackNode** top, char data);
char Pop(struct StackNode** top);
char GetTop(struct StackNode* top);

struct QueueNode
{
        float data;
        struct QueueNode* next;
};
void InitQueue(struct QueueNode** front, struct QueueNode** rear);
void EnQueue(struct QueueNode** rear, float data);
float DeQueue(struct QueueNode* front, struct QueueNode** rear);
void QueueTraverse(struct QueueNode* front);
void DestroyQueue(struct QueueNode** front, struct QueueNode** rear);

int Priority(char op);

void main()
{
        // 保存操作符的栈
        struct StackNode* top = NULL;
        // 队列中要存放的是转换后的逆波兰表达式就是后缀表达式
        struct QueueNode* front = NULL;
        struct QueueNode* rear = NULL;
        float num;
        char ch, e;
        InitQueue(&front, &rear);
        printf("请输入中缀表达式, 以回车键结束输入:\n");
        do
        {
                scanf("%c", &ch);
                switch ( ch )
                {
                case ' ': break;         // 过滤掉空格
                // 检测到键盘缓冲区中有数字开始的字符
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': 
                        ungetc(ch, stdin);         // pay attention !
                        scanf("%f", &num);         // 以浮点数的格式从键盘缓冲区获得一个操作数(整数同样也可以读取)
                        EnQueue(&rear, num); break;         // 将读取到的操作数入队
                // 碰到左括号,先放入操作符栈
                case '(': 
                        Push(&top, ch); break;
                // 碰到有括号, 由于括号隔离了优先级, 则需要先计算左右括号之间的表达式
                case ')':
                case '\n':  // pay attention! 加'\n'是考虑到读取到最后的一个结束字符时栈中还有一个操作符并没有参与运算
                        // top时刻指向操作符的栈顶,当栈中存在操作符且操作符位于左右括号之间时才将栈中的操作符弹出栈,然后放入操作数队列
                        while ( top && ( e=Pop(&top), e!='(' ) )
                        {
                                EnQueue(&rear, e);
                        }
                        break;
                // 四则运算
                case '+':
                case '-':
                case '*':
                case '/':
                        // 判读优先级,如果当前读入的操作符优先级低于栈顶操作符优先级则说明栈顶操作符的优先级别高,将它弹出栈并入操作数队列
                        while ( Priority(ch) <= Priority(GetTop(top)) )
                        {
                                e = Pop(&top);
                                EnQueue(&rear, e);
                        }
                        Push(&top, ch);
                        break;
                default:
                        printf("表达式非法!\n");
                        exit(0);
                }
        } while( ch!='\n' );

        // 此时队列中存放的是转换好的逆波兰表达式(后缀表达式),有了逆波兰表达式就可以进一步的求出表达式的值了(不难的求的)^-^
        QueueTraverse(front);

        DestroyQueue(&front, &rear);

        _getch();

}

int Priority(char op)
{
        switch ( op )
        {
        case '(':
        case '#':
                return 0;
        case '-':
        case '+':
                return 1;
        case '*':
        case '/':
                return 2;
        default:
                return -1;
        }
}

void Push(struct StackNode** top, char ch)
{
        struct StackNode* p = (struct StackNode*)malloc(sizeof(struct StackNode));
        p->data = ch;
        p->next = *top;
        *top = p;
}
char Pop(struct StackNode** top)
{
        struct StackNode* p = *top;
        char e;
        if ( p == NULL )
        {
                printf("下溢!\n");
                exit(0);
        }
        e = p->data;
        *top = p->next;
        free(p);
        return e;
}

char GetTop(struct StackNode* top)
{
        if ( top == NULL )
        {
                return -1;
        }
        return top->data;
}

void InitQueue(struct QueueNode** front, struct QueueNode** rear)
{
        struct QueueNode* p = (struct QueueNode*)malloc(sizeof(struct QueueNode));
        p->next = NULL;
        *front = *rear = p;
}

void EnQueue(struct QueueNode** rear, float e)
{
        if ( *rear == NULL )
        {
                printf("队列已被销毁或者还没有被初始化, 请初始化队列!");
        }
        else
        {
                struct QueueNode* p = (struct QueueNode*)malloc(sizeof(struct QueueNode));
                p->data = e;
                p->next = NULL;
                (*rear)->next =  p;
                *rear = p;
        }
}

float DeQueue(struct QueueNode* front,struct QueueNode** rear)
{
        float e;
        if ( front == NULL )
        {
                printf("队列已被销毁或者还没有被初始化, 请初始化队列!\n\n");
        }
        else
        {
                if ( front == *rear )
                {
                        printf("队列为空, 无法出队!\n\n");
                }
                else
                {
                        struct QueueNode* p = front->next;
                        e = p->data;
                        front->next = p->next;
                        if ( p == *rear )
                        {
                                *rear = front;
                        }
                        free(p);
                }
        }
        return e;
}

void QueueTraverse(struct QueueNode* front)
{
        struct QueueNode* p = front;
        if ( p == NULL )
        {
                printf("队列已被销毁或者还没有被初始化, 请初始化队列!");
        }
        else
        {
                if ( p->next == NULL )
                {
                        printf("队列为空!");
                }
                else
                {
                        printf("队列中的元素为: ");
                        while ( p->next != NULL )
                        {
                                p = p->next;
                                switch ( (char)p->data )
                                {
                                case '+':
                                case '-':
                                case '*':
                                case '/':
                                        printf("%c ", (char)p->data); break;
                                default:
                                        printf("%f ", p->data);
                                }
                        }
                }
        }
        printf("\n");
}

void DestroyQueue(struct QueueNode** front, struct QueueNode** rear)
{
        while( *front )
        {
                *rear = (*front)->next;
                free(*front);
                *front = *rear;
        }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-12-19 00:37:34 | 显示全部楼层
^-^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-12-19 22:40:21 | 显示全部楼层
非常感谢楼主
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-12-21 23:30:48 | 显示全部楼层
非常感谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-12-22 23:07:40 | 显示全部楼层
感谢分享
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-12-23 13:36:18 | 显示全部楼层

很高心能帮助到你^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-22 20:44

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表