栈的基本操作和相关练习题

一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操 作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。不含任 何元素的栈称为空栈,同样栈可以分为顺序栈和链栈。

栈的结构:

 

栈特性:后进先出(LILO)特殊线性表   。

栈功能:将数据从一种序列改变到另一种序列  。

顺序栈的结构c语言描述:

typedef struct Stack
{
    SDataType _array[MAXSIZE];
    int _top; // 标记栈顶(栈中元素的个数) 
}Stack;

栈的基本操作:

void StackInit(Stack* ps)//初始化
{
    ps->_top = -1;

}
void StackPush(Stack* ps, SDataType data)//进栈
{
    assert(ps);
    if (ps->_top == MAXSIZE - 1)
        printf("栈已满\n");
    else
    {
        ps->_top++;
        ps->_array[ps->_top] = data;

    }


}
void StackPop(Stack* ps)//出栈
{
    assert(ps);
    if (ps->_top == -1)
        printf("栈已空\n");
    ps->_top--;


}
SDataType StackTop(Stack* ps)//获取站顶元素
{
    assert(ps);
    if (ps->_top == -1)
        printf("栈已空\n");
    return ps->_array[ps->_top];

}
int StackSize(Stack* ps)//栈中的元素个数
{
    return (ps->_top) + 1;
}
int StackEmpty(Stack* ps)//判空
{
    if (ps->_top == -1)
        return 1;
    else
        return 0;
}

栈的练习题:

括号匹配问题;

首先检测获取的元素是否是括号,如果是那么检测是否是左括号,如果是那么将该元素进栈,如果不是左括号检测是否是右括号若果是此时要判断栈是否为空(栈空那么表示右括号多于左括号,如果栈不为空判断两个括号是否匹配如果不匹配那么则匹配出错)出循环判断栈是否为空不为空表示左比右多。否则匹配正确

1.

//判断元素是否是括号

int IsBrackets(char arr[], int i)
{
    if ((arr[i] == '(') || (arr[i] == '[') || (arr[i] == '{') || (arr[i] == ')') || (arr[i] == ']') || (arr[i] == '}'))
        return 1;
    return 0;
}
void MatchBrackets(Stack* ps, int sz, char arr[])
{
    assert(ps);
    int i = 0;
    while (i < sz)
    {

        if (IsBrackets(arr, i))
        {
            if ((arr[i] == '(') || (arr[i] == '[') || (arr[i] == '{'))
            {
                StackPush(ps, arr[i]);
                i++;
                continue;
            }
            else if((arr[i] ==')') || (arr[i] == ']') || (arr[i] == '}'))
            { 
                if (StackEmpty(ps))
                {
                    printf("右括号比做坐括号多\n");
                    return;
                }
                else
                {
                    if ((arr[i] == ')'&&StackTop(ps) == '(') || (arr[i] == ']'&&StackTop(ps) == '[') || (arr[i] == '}'&&StackTop(ps) == '{'))
                    {

                        StackPop(ps);
                        i++;
                        continue;
                    }
                    else
                    {
                        printf("匹配出错\n");
                        return;
                    }
                }


            }
        }
        i++;

        

    }
    if (!StackEmpty(ps))
    {
        printf("左括号比右括号多\n");

    }
    else
        printf("匹配正确\n");
}

后缀表达式:

12*(3+4)-6+8/2 —–> 12 3 4 + * 6 - 8 2 / +  
考虑到在有较大数参与运算时不好处理,现将表达式封装成一个数组,再将数组传给函数如下:

operate  cal[] = { { DATA, 12 }, { DATA, 3 }, { DATA, 4 }, { ADD, 0 }, { MUL, 0 },
    { DATA, 6 }, { SUB, 0 }, { DATA, 8 }, { DATA, 2 }, { DIV, 0 }, { ADD, 0 } };

所需结构体

typedef struct Stack
{
    SDataType _array[MAXSIZE];
    int _top; // 标记栈顶(栈中元素的个数) 
}Stack;
enum Calc
{
    ADD,
    SUB,
    MUL,
    DIV,
    DATA

};
typedef struct operate
{
     enum calc op;
    int _data;
}operate;

函数实现:

int CalcRPN(operate *cal, Stack *ps, int size)
{
    int i = 0;
    int right = 0;
    int left = 0;
    int ch = 0;
    while (i < size)
    {
        if (cal->op == DATA)
            StackPush(ps, cal->_data);//12*(3+4)-6+8/2 —–> 12 3 4 + * 6 - 8 2 / +  
        else
        {
            ch = cal->op;
            right = StackTop(ps);
            StackPop(ps);
            left = StackTop(ps);
            StackPop(ps);

            switch (ch)
            {
            case ADD:StackPush(ps, left + right);
                break;
            case SUB:StackPush(ps, left - right);
                break;
            case MUL:StackPush(ps, left * right);
                break;
            case DIV:
                if (right == 0)
                {
                    printf("除数为0,非法!!!\n");
                    return 0;
                }
                else
                {
                    StackPush(ps, left / right);
                }
                break;
            default:printf("操作数非法!!\n"); break;

            }
        
        }
        i++;
        cal++;
    }
    return StackTop(ps);
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值