【数据结构】栈和队列相关例题(C/C++含注释)

文章目录

      • 一、判断字符串镜像——栈
      • 二、表达式求值问题
      • 三、银行排队——队列

一、判断字符串镜像——栈

【问题描述】

试写一个算法,识别依次读入的一个以“@”为结束符的字符序列是否为形如 “序列1&序列2” 模式的字符序列。其中序列1和序列2都不含字符 “&”,且序列2是序列1的逆序列。例如,“ a+b&b+a ”是属该模式的字符序列,而 “1+3&3-1”则不是。

【输入形式】

以@为结尾的一串字符

【输出形式】

若符合模式则输出字符串长度,否则输出no

【样例输入】

a+b&b+a@

【样例输出】

3

【完整代码】

#include 
#include 
#define Stack_Size 1005                   //设栈中元素个数为50
#define StackElementType char
#define FALSE 0
#define TRUE 1

typedef struct
{
    StackElementType elem[Stack_Size];  //用来存放栈中元素的一维数组
    int top;                            //用来存放栈顶元素的下标,top为-1表示空栈
}SeqStack;                              //顺序栈

void InitStack( SeqStack * S )          //初始化
{   /*造一个空栈*/
    S->top = -1;
}

int Push( SeqStack * S, StackElementType x )//进栈
{   /*将x置入S栈新栈顶*/
    if( S->top == Stack_Size-1 ) return FALSE;//栈已满
    S->top++;                           //修改栈顶指针
    S->elem[S->top] = x;                //x进栈
    return TRUE;
}

int Pop( SeqStack * S, StackElementType * x )//出栈
{   /*将S栈顶元素弹出,放到x所指的存储空间中带出*/
    if( S->top == -1 ) return FALSE;    //栈为空
    else
    {
        *x = S->elem[S->top];           //栈顶元素赋给x
        S->top--;                       //修改栈顶指针
        return TRUE;
    }
}

int GetTop( SeqStack * S, StackElementType * x )//读取栈顶元素
{   /*将栈S栈顶元素读出,放到x所指的存储空间中,栈顶指针保持不变*/
    if( S->top == -1 ) return FALSE;    //栈为空
    else
    {
        *x = S->elem[S->top];           //栈顶元素赋给x
        return TRUE;
    }
}

int main()
{
    char temp;
    int ans = 0;
    char * x = (char *)malloc(sizeof(char));
    SeqStack * S = (SeqStack *)malloc(sizeof(SeqStack));
    InitStack(S);
    while( scanf("%c",&temp) ) //压栈,直到'&'停止压栈
    {
        if( temp=='&' ) break;
        Push(S,temp);
    }
    while( scanf("%c",&temp) )
    {
        if( GetTop(S,x) )    //读取栈顶元素且栈不为空
        {
            if( *x==temp )  //如果匹配
            {
                ans++;      //计数+1
                Pop(S,x);   //弹出栈顶元素
                continue;
            }
            else
            {
                printf("no\n");
                return 0;
            }
        }
        else
        {
            if( temp=='@' )
            {
                break;
            }
            else
            {
                printf("no\n");
                return 0;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

二、表达式求值问题

【问题描述】

栈的应用,给定一个以“#”作为结束符的算式,求出算式的结果

【输入形式】

以“#”结尾的表达式,运算数为正整数。每个表达式占一行。

【输出形式】

输出表达式运算的结果。注意分别运用C语言和C++语言如何处理表达式中带小数的数据,输出数据请保留2位小数。

【样例输入】

4+2.53*3-10/5#

3*(7.91-2)#

2.4*3.6/2#

【样例输出】

9.59

17.73

4.32

【完整代码】

#include 
using namespace std;
template <typename T>
//构造栈
struct mstack
{
    T a[1000];
    int top;
    //压栈
    void push(T t)
    {
        top++;
        a[top]=t;
    }
    //出栈
    void pop()
    {
        top--;
    }
    //获得栈顶元素
    T gettop()
    {
        return a[top];
    }
};
//判断运算符优先级
/* 运算符优先级表
	'>','>','<','<','<','>','>',
	'>','>','<','<','<','>','>',
	'>','>','>','>','<','>','>',
	'>','>','>','>','<','>','>',
	'<','<','<','<','<','=',' ',
	'>','>','>','>',' ','>','>',
	'<','<','<','<','<',' ','='
*/
char Compare(char x,char ch)
{
	switch(x)
	{
	case '+':
		if(ch=='+'||ch=='-'||ch==')'||ch=='#')
			return '>';
		else if(ch=='*'||ch=='/'||ch=='(')
				return '<';
		break;
	case '-':
		if(ch=='+'||ch=='-'||ch==')'||ch=='#')
			return '>';
		else if(ch=='*'||ch=='/'||ch=='(')
			return '<';
		break;
	case '*':
		if(ch=='(')
		{
			return '<';
		}
		else
		{
			return '>';
		}
		break;
	case '/':
		if(ch=='(')
				return '<';
		else
				return '>';
		break;
	case '(':
		if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='(')
			return '<';
		else if(ch==')')
			return '=';
		else if(ch=='#')
			return '0';
		break;
	case ')':
		if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch==')'||ch=='#')
			return '>';
		else if(ch=='(')
			return '0';
		break;
	case '#':
		if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='(')
			return '<';
		else if(ch=='#')
			return '=';
		else if(ch==')')
			return '0';
		break;
	default:
		return '0';
		break;
	}
    return '0';
}
//判断输入的是操作符还是操作数
bool isoper(char c)
{
    if(c>='0'&&c<='9')
        return false;
    return true;
}
//进行计算
double fun(char c,double x,double y)
{
    switch(c)
    {
    case '+':return x+y;
    case '-':return x-y;
    case '*':return x*y;
    case '/':return x/y;
    }
    return -100;
}
int main()
{
    char ch;
    double x;
    while(cin>>ch)
    {
        mstack<double> A;
        mstack<char> B;
        A.top=B.top=-1;
        B.push('#');
        while(1)
        {
            if(!isoper(ch))
            {
                cin.putback(ch);
                cin>>x;
                A.push(x);
                cin>>ch;
            }
            else
                //判断运算符优先级
                switch(Compare(B.gettop(),ch))
                {
                case '<':
                    B.push(ch);
                    cin>>ch;
                    break;
                case '>':
                    double left,right;
                    right=A.gettop();
                    A.pop();
                    left=A.gettop();
                    A.pop();
                    A.push(fun(B.gettop(),left,right));
                    B.pop();
                    break;
                case '=':
                    B.pop();
                    if(ch==')')cin>>ch;
                    break;
                }
            if(B.top==-1)
            {
                cout<<fixed<<setprecision(2)<<A.gettop()<<endl;
                break;
            }
        }
    }
    return 0;
}

三、银行排队——队列

【问题描述】

根据课堂讲授的事件驱动模拟案例,请用顺序队列或链式队列来完成本题。

我们大多都有在银行排队的经历,唉,那坑爹的排队啊!现在就让我们来算算我们这些客户平均需要等多久吧。
每天刚开始时银行会开m个窗口来为我们total个客户办理业务,当有客户需要办理业务时,先选择可以办理业务的窗口,如果有多个窗口可以办理业务就选择空闲时间最长的窗口,如果有多个窗口空闲的时间一样长,则选择序号小的窗口办理业务。假设我们每个人来到的时间和办理业务所需要的时间(为了简化问题,采用整数表示时间)都知道了。现在请你算算我们平均需要等待多久呢?

【输入形式】

有多组测试数据,每组数据开始有两个正整数m(<20)和total(<200),后面有total对整数,对应客户先后到来的时间以及办理业务所需的时间。

【输出形式】

平均等待的时间,保留两位小数。

【样例输入】

2 6 1 3 4 1 5 3 9 2 13 4 13 3
3 14 0 3 2 2 2 4 5 4 7 2 11 3 12 3 12 4 12 1 13 3 15 4 19 1 22 3 23 2
2 5 0 6 0 5 0 6 7 1 7 2

【样例输出】

0.00
0.29
1.20

【提示】

题目中选择办理的窗口有三个状态,实际上从序号自小到大查找可以最早办理业务的窗口就已经满足上述三个状态了。

【完整代码】

//银行排队
#include
#include
#include
using namespace std;

int main() 
{
    int m, t;
    while (cin >> m >> t) 
    {   //m:办理业务的银行窗口数 
        //t:整个过程办理业务的人数   
        //这一个while循环完,求出了在一个情形下的情况
        int a, b;             //a:每一个客户到来的时间 b:该客户办理业务的时间
        int sum = 0;          //办理业务等待时间
        int q[20];            //窗口数,上限20个
        memset(q,0,sizeof(q));//把该数组所有值先置为0
        for (int i = 0; i < t; i++) 
        {
            cin >> a >> b;
            int cur = 0;      //要去选出哪个窗口办理完上一个业务最快
            int min = q[0];
            for (int i = 0; i < m; i++) 
            {
                if (q[i] <min) 
                {
                    min = q[i];
                    cur = i;
                }
            }                 //从min到这,是找出这几个窗口最小的时间,下一个客户到哪个窗口去办理业务
            if (a < q[cur]) 
            {   //如果a到达的时间比所有的办理业务结束的时间还要小,那么它就得等,sum就要++了
                q[cur]:最早结束业务的窗口(eg:24)
                //a:到来的时间(eg:19),那么就得等24-19=5分钟;
                sum += (q[cur] - a);
                //那么这个窗口就又添了一个新业务(在这个窗口等肯定就要在这办啊),所以这个窗口结束业务的时间就要再加+b
                //上一个人走,新客户立马办,不用加排队的时间
                q[cur] += b;
            }
            else 
            {   //如果a:到达的时间比这个q[cur]小,就是说现在有空余的窗口,那么就直接在这办理业务了
                //那么这个空余的窗口就有了新业务,结束业务的时间:a+b
                //假设上一个人办完业务是5分走的,8分来了新客人,办理业务3分钟,所以这个窗口结束业务的时间8+3=11分钟
                q[cur] = a + b;
            }
        }
        printf("%.2f\n", sum*1.0/t);
    }
    return 0;
}

你可能感兴趣的:(#,数据结构,数据结构,栈,队列)