Data Structure Note 2: Stack

Data Structure Note 2: Stack

LIFO stack is a linear form, or with more generally sequential storage structure, with fewer link stack.

Note that the key top pointer indicates the next position of the last element pushed onto the stack;

base pointer to the first address, also points to the first element of the stack; use realloc function; the difference between empty and destroyed stack.

s.base-s.top difference is the number of elements in the stack at this time, because of the different address pointer value +1 +1

First, the following is a stack-based calculator to achieve the mixing operation can be achieved.

Here Insert Picture Description
Here Insert Picture Description

Stack.h

#ifndef _STACK_H_
#define _STACK_H_
using namespace std;
typedef int status;
typedef char ElemType;
#define ERROR -1
#define OK 1
typedef struct StackList
{
    ElemType *top; //指向栈顶的指针
    ElemType *base;//指向栈底的指针
    int stacksize;//存储栈的大小,如果不够是在这里扩容
    //主要用处是方便判断栈满
}Stack;

/***********************************************************/
status Stack_Init(Stack &s);
status Stack_IfFull(Stack &s);//判断栈是否为满,为满则返回OK
status Stack_IfEmpty(Stack &s);//判断栈是否为空,为空则返回OK
status Stack_Push(Stack &s,ElemType &e);
status Stack_Pop(Stack &s,ElemType &e);
ElemType Stack_GetTop(Stack s);
status Stack_Clear(Stack &s);
status Stack_Destroy(Stack &s);

#endif

Stack.cpp

#include <iostream>
#include <Stack.h>
#include <cstdlib>
using namespace std;
#define STACKINITSIZE 100 //这里是给栈初始化时分配内存的
#define STACKINCREMENT 10
/*************************************************************/
status Stack_Init(Stack &s) 
{
    s.base = (ElemType*)malloc(STACKINITSIZE * sizeof(ElemType));
    s.top = s.base;
    s.stacksize = STACKINITSIZE;//初始化时分配好栈的大小
    return OK;
}
status Stack_IfFull(Stack &s)
{
    if(s.top-s.base >= s.stacksize) //两个指针指向的地址相减得到此时栈的大小(即所占空间大小)
    return OK;
    else
    return 0;
}
status Stack_IfEmpty(Stack &s)
{
    if(s.top == s.base) //两个指针指向相同地址
    return OK;
    else
    return 0;
}
status Stack_Push(Stack &s,ElemType &e)
//感觉这个地方e不用引用直接传参也可以啊,可能就是省的额外给形参分配空间了吧
//这里注意一下,top指向的是最后一个入栈元素的下一个位置,而不是最后一个入栈的元素
//而base作为栈的起始指针,其实是指向最早入栈的元素的,而不存在一个空位置专门存放base指针
{
    if(Stack_IfFull(s))//先判断栈有没有满
    {
        s.base = (ElemType*)realloc(s.base,(s.stacksize + STACKINCREMENT) 
        * sizeof(ElemType));//相当于重新分配了一段内存,把原来栈的内容直接复制过去
        if(!s.base) return ERROR;
        s.top = s.base + s.stacksize;//栈的位置变了,top指针不再是指向原来的地方,重新赋值
        s.stacksize += STACKINCREMENT;//扩容,其实是起标示作用
    }
    *(s.top) = e;
    s.top++;
    return OK;
}
status Stack_Pop(Stack &s,ElemType &e)//出栈,并用e保存出栈元素
{
    if(s.base == s.top) return ERROR;
    s.top--;
    e = *(s.top);
    return OK;
}
ElemType Stack_GetTop(Stack s)//得到栈顶元素,因为不能改变栈本身的结构,
//但是需要操作top指针,因此这里不用引用而用形参操作,函数主体与出栈类似
{
    ElemType e;
    if(s.base == s.top) return ERROR;
    s.top--;
    e = *(s.top);
    return e;
}
status Stack_Clear(Stack &s)//清空栈,不用释放存储空间
{
    s.top = s.base;//top指到base就行了
    return OK;
}
status Stack_Destroy(Stack &s) //完全释放
{
    int i,len;
    len = s.stacksize;
    for(i=0;i<len;i++)
    {
        free(s.base);//利用base指针清除,清除后指向下一个元素
        s.base++;
    }
    s.base = s.top =NULL;
    s.stacksize = 0;
    return OK; 
}

Culculate.h

#ifndef _CULCULATE_H_
#define _CULCULATE_H_
#include "Stack.h"
status char_or_num(char a);
char cul_plus(char a,char b);
char cul_minus(char a,char b);
char cul_mul(char a,char b);
char cul_div(char a,char b);
int culculate(Stack s,char str[],int &len);
int judge(char a);
status translate(Stack &s,char str1[],char str2[],int &strlen);
#endif

Culculate.cpp

#include"Culculate.h"
#include <iostream>
#include "stdlib.h"
status char_or_num(char a)//判断数字还是字符
{
    if(a>='0' && a<='9')
    return 1;
    else return 0;
}
char cul_plus(char a,char b)//字符加法
{
    int c;
    char m;
    c = (int(a)-48) + (int(b)-48);
    m = c + 48;
    return m;
}
char cul_minus(char a,char b)//字符减法
{
    int c;
    char m;
    c = (int(a)-48) - (int(b)-48);
    m = c + 48;
    return m;
}
char cul_mul(char a,char b)//字符乘法
{
    int c;
    char m;
    c = (int(a)-48) * (int(b)-48);
    m = c + 48;
    return m;
}
char cul_div(char a,char b)//字符除法
{
    int c;
    char m;
    c = (int(a)-48) / (int(b)-48);
    m = c + 48;
    return m;
}
int judge(char a)//判断符号优先级
{
    int ret;
    if(a == '*'|| a == '/')
    ret = 2;
    if(a == '+'|| a == '-')
    ret = 1;
    return ret;
}
//translate函数,将标准表达式转化乘逆波兰表达式。
//具体思路,遍历字符串,遇到数字直接放到str2中,碰到运算符号
//左括号入栈,等待匹配右括号,匹配成功的话把左右括号中的符号全部输出,包括括号出栈
//*/的优先级高于+-,碰到*/入栈(优先级不低于栈顶元素),碰到+-让元素全部出栈(没有比+-优先度低的),
//再将该元素入栈。全部遍历后再把栈里剩余元素全部输出。
status translate(Stack &s,char str1[],char str2[],int &strlen)
{
    int i,j;
    int len = 0;
    char e;
    while(1)
    {
        if(str1[len] == '\0') break;
        len++;
    }
    for(i = 0,j = 0;i<len;i++)
    {
        if(char_or_num(str1[i]))//输出数字
        {
            str2[j] = str1[i];
            j++;
        }
        else
        {
            if(str1[i] == '('||str1[i] == ')')//匹配括号
            {
                if(str1[i] == '(')
                    Stack_Push(s,str1[i]);
                if(str1[i] == ')')
                {
                    while(Stack_GetTop(s) != '(')
                    {
                        Stack_Pop(s,str2[j]);
                        j++;
                    }
                    Stack_Pop(s,e);
                }
            }
            else
            {  //判断优先级
                if((judge(str1[i]) > judge(Stack_GetTop(s)))||Stack_IfEmpty(s))
                {
                    Stack_Push(s,str1[i]);
                }
                else
                {
                    while(!Stack_IfEmpty(s))
                    {
                        Stack_Pop(s,str2[j]);
                        j++;
                    }
                    Stack_Push(s,str1[i]);
                }
            }
            
        }        
    }
    while(!Stack_IfEmpty(s))//输出剩余元素
    {
        Stack_Pop(s,str2[j]);
        j++;
    }
    strlen = j+1;
    Stack_Clear(s);//记得清空用过的栈给之后用
    return OK;
}
//碰到数字,入栈;碰到运算符,让栈的倒数两个元素出栈进行运算,运算结果入栈。直到运算结束。
int culculate(Stack s,char str[],int &len)
{
    int i,cul;
    char nex,pre,ret;
    Stack_Push(s,str[0]);
    for(i=1;i<len;i++)
    {
        if(char_or_num(str[i]))
        {
            Stack_Push(s,str[i]);//是数字,入栈
        }
        else
        {
            Stack_Pop(s,nex);
            Stack_Pop(s,pre);//栈顶两个元素出栈
            switch(str[i])
            {
                case '+':ret = cul_plus(pre,nex);break;
                case '-':ret = cul_minus(pre,nex);break;
                case '*':ret = cul_mul(pre,nex);break;
                case '/':ret = cul_div(pre,nex);break;
            }
            Stack_Push(s,ret);//运算完的结果入栈
        }   
    }
    ret = Stack_GetTop(s);//最后栈中只剩一个元素为运算结果
    cul = int(ret)-48;
    return cul;
}

main.cpp

#include "Stack.h"
#include "Culculate.h"
#include <iostream>
using namespace std;
int a[3] = {1,2,3};
/**************************字符串计算器逆波兰表达式运算求解**************************/
/***********这个计算器存在弊端,输入的数只能是0-9以内,大于9的数在整型字符型转换上相对复杂一些******/

//"9*2-(7+1)/((2+2)*2)="; //例子
char str1[22];
char str2[20];
int main()
{
    Stack s;
    int i = 0;
    Stack_Init(s);
    cout << "本计算器可运算混合运算,但输入的数字只能是0-9内的,主要还是本人太菜了"<<endl;
    cout << "请输入运算表达式,输入“=”按下回车开始运算"<<endl;
    int cul,len;
    for(i=0;;i++) //输入原表达式
    {
        cin >> str1[i];//可以直接把表达式敲进去
        if(str1[i] == '=')//输入结束
        {
            str1[i] = '\0';
            break;
        }
    }
    translate(s,str1,str2,len);//翻译成逆波兰表达式
    i = 0;
    cout << "逆波兰表达式为:";
    while(str2[i] != '\0')//输出翻译后的逆波兰表达式
    {
        cout << str2[i];
        i++;
    }
    cout << endl;
    cul = culculate(s,str2,len);
    cout << "计算结果为:";
    cout << cul <<endl;
    return 0;
}

operation result

Here Insert Picture Description

Error-prone finishing:

1、Here Insert Picture Description
Here Insert Picture Description

2,
Here Insert Picture Description
Here Insert Picture Description
3, top of the stack top, team head, the tail of the definition is not the only team to examine the topic.

For example, top most cases refers to the last element of the stack to the next position, sometimes pointing to the last question in the

Elements of the stack.

4, the shared stack more efficient use of storage space, the data access time complexity of O (1), an overflow may occur.

Released five original articles · won praise 5 · Views 361

Guess you like

Origin blog.csdn.net/gaiyi7788/article/details/104110677