《数据结构与算法分析》学习笔记(四)——栈ADT

一、栈ADT是what?

1、定义

        栈,是限制插入和删除都只能在一个位置上进行的表。

2、图示        

                               

3、栈的基本功能

(1)是否为空

(2)进栈

(3)出栈

(4)清空

(5)取栈顶

二、栈的链表实现

 

#ifndef Exercise_Stack_h

#define Exercise_Stack_h



typedef struct Node *PrtToNode;

typedef PrtToNode Stack;

typedef int ElementType;





struct Node

{

    ElementType Element;

    PrtToNode Next;

};





bool IsEmpty(Stack S);



Stack CreateStack();



void MakeEmpty(Stack S);



void Push(ElementType X,Stack S);



void Pop(Stack S);



ElementType Top(Stack S);



#endif













bool IsEmpty(Stack S)

{

    return S->Next==nullptr;

}





Stack CreateStack()

{

    Stack S;

    

    S = new struct Node;

    if(S==nullptr)

    {

        std::cout<<"Create Error!"<<std::endl;

        return nullptr;

    }

    

    S->Next=nullptr;



    return S;

}



void MakeEmpty(Stack S)

{

    if(S==nullptr)

    {

        std::cout<<"not initStack Error!"<<std::endl;

        return ;

    }

    

    while (!IsEmpty(S))

    {

        Pop(S);

    }

    

}





void Push(ElementType X,Stack S)

{

    PrtToNode Temp;

    

    Temp = new struct Node;

    if(Temp==nullptr)

    {

        std::cout<<"init Node Error!"<<std::endl;

        return;

    }

    

    Temp->Element=X;

    Temp->Next=S;

    S->Next=Temp;

}





void Pop(Stack S)

{

    if(IsEmpty(S))

    {

        std::cout<<"Stack Empty!"<<std::endl;

        return;

    }

    auto temp = S->Next;

    S->Next=S->Next->Next;

    delete temp;

}





ElementType Top(Stack S)

{

    if(IsEmpty(S))

    {

        std::cout<<"Stack Empty!"<<std::endl;

        return  0;

    }

    return S->Next->Element;

}

PS:优点:不用担心栈溢出的现象

       缺点:开辟内存和释放内存的时候貌似开销比较昂贵。

 

三、栈的数组实现

typedef int ElementType;

const int MaxCapacity = 100;



struct StackRecord

{

    int Capacity;

    int TopOfStack;

    ElementType *Array;

};



typedef struct StackRecord *Stack;



bool IsFull(Stack S);



bool IsEmpty(Stack S);



Stack CreateStack(int MaxElements);



void DisposeStack(Stack S);



void MakeEmpty(Stack S);



void Push(ElementType X,Stack S);



void Pop(Stack S);



ElementType Top(Stack S);



ElementType TopandPop(Stack S);











Stack CreateStack(int MaxElements)

{

    Stack S;

    

    S = new struct StackRecord;

    if(S==nullptr)

    {

        std::cout<<"Out of space!"<<std::endl;

        return nullptr;

    }

    

    S->Array = new ElementType(MaxElements);

    if(S->Array==nullptr)

    {

        std::cout<<"Out of space!"<<std::endl;

        return nullptr;

    }

    

    S->Capacity=MaxElements;

    S->TopOfStack=-1;

    

    MakeEmpty(S);

    

    return S;

    

}



void DisposeStack(Stack S)

{

    if(S!=nullptr)

    {

        delete S->Array;

        delete S;

    }

}





bool IsEmpty(Stack S)

{

    return S->TopOfStack==-1;

}



void MakeEmpty(Stack S)

{

    S->TopOfStack=-1;

}



void Push(ElementType X,Stack S)

{

    if(IsFull(S))

    {

        std::cout<<"Full Stack"<<std::endl;

        return;

    }

    S->Array[++S->Array[S->TopOfStack]]=X;

             

}



ElementType Top(Stack S)

{

    if(!IsEmpty(S))

    {

        return S->Array[S->TopOfStack];

    }

    

    std::cout<<"Empty Error"<<std::endl;

    return 0;

}



void Pop(Stack S)

{

    if(IsEmpty(S))

    {

        std::cout<<"Empty Error"<<std::endl;

    }

    else{

        S->TopOfStack--;

    }

}



ElementType TopandPop(Stack S)

{

    if(!IsEmpty(S))

    {

        return S->Array[S->TopOfStack--];

    }

    std::cout<<"Empty Error"<<std::endl;

    return 0;



}



bool IsFull(Stack S)

{

    return S->Capacity==MaxCapacity;

}

优点:把不断开空间的时间省下来了;

缺点:数组商都是有限的;

 

 

四、应用

(1)括号的匹配

void test(string s)

{

    auto stack = CreateStack(100);

    

    for(auto c: s)

    {

        if(c=='['||c=='{'||c=='(')

        {

            Push(c, stack);

        }

        else

        {

           if(c==']'||c=='}'||c==')')

           {

               if(IsEmpty(stack))

               {

                   cout<<"Error!"<<endl;

               }

               else

               {

                  if(c==']')

                  {

                      auto temp = TopandPop(stack);

                      if(temp!='[')

                      {

                          cout<<"Error!"<<endl;

                      }

                  }

                   else if(c=='}')

                   {

                       auto temp = TopandPop(stack);

                       if(temp!='{')

                       {

                           cout<<"Error!"<<endl;

                       }

                   }

                   else if(c==')')

                   {

                       auto temp = TopandPop(stack);

                       if(temp!='(')

                       {

                           cout<<"Error!"<<endl;

                       }

                   }

                   else

                   {

                       cout<<"Scanf Error!"<<endl;

                   }



               }

           }

           else

           {

               cout<<"Scanf Error!"<<endl;

           }

        }

        

    }

    

    if(stack->TopOfStack==-1)

    {

        cout<<"RIGHT"<<endl;

    }

    else

    {

        cout<<"Error!"<<endl;

    }

    

}

(2)后缀表达式的计算。

后缀表达式的优点就是完全不需要考虑什么优先级之类的,直接从左边算到右边就可以了,简直方便快捷,在这里我就默默的实现下,小白勿喷

int calculate(string S)     //10以内的整数运算

{

    

    auto stack = CreateStack(100);

    

    

    for(auto c:S)

    {

        switch (c)

        {

            case '+' :

            {

                auto t1=TopandPop(stack);

                auto t2=TopandPop(stack);

                double t3=t1+t2;

                

                Push(t3, stack);

            }

                

                break;

                case '-':

            {

                auto t1=TopandPop(stack);

                auto t2=TopandPop(stack);

                double t3=t2-t1;

                

                Push(t3, stack);

            }

                break;

                case '*':

            {

                auto t1=TopandPop(stack);

                auto t2=TopandPop(stack);

                double t3=t2*t1;

                

                Push(t3, stack);

            }

                break;

                case '/':

            {

                auto t1=TopandPop(stack);

                auto t2=TopandPop(stack);

                double t3=t2/t1;

                

                Push(t3, stack);

            }

                break;

            default:

            {

                Push(c-'0', stack);

            }

                break;

        }

    }

    

    

    return Top(stack);

    

}

 3、中缀表达式转化成后缀表达式

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<vector>

#include<stack>

#include<algorithm>

using namespace std;



int pre(char a) //操作符优先级比较

{

    if(a == '=' || a == '(')

        return 0;

    else if(a == '+' || a == '-')

        return 1;

    else if(a == '*' || a == '/')

        return 2;

    else

    {

        cout<<"Error!"<<endl;

        return 0;

    }

}



int main()

{

    string str;

    stack<char> ope; //操作符

    vector<char> ans;//后缀表达式

    vector<char>::iterator start, end;

        getchar(); //清除输入垃圾

    

        while(!ope.empty()) //初始化

            ope.pop();

        ans.clear();

        ope.push('='); //结束标志

        cin>>str;

        auto len = str.length();

        for(int i = 0 ; i < len; ++i)

        {

            if(str[i] >= '0' && str[i] <= '9') //操作数直接存入ans

                ans.push_back(str[i]);

            else if(str[i] == '(') //左括号入栈

                ope.push(str[i]);

            else if(str[i] == ')') //右括号,将匹配的左括号内容存入ans,左括号出栈

            {

                while (ope.top() != '(')

                {

                    ans.push_back(ope.top());

                    ope.pop();

                }

                ope.pop(); //左括号出栈

            }

            else if(pre(str[i]) > pre(ope.top())) //优先级大于栈顶元素则入栈

                ope.push(str[i]);

            else //小于栈顶元素

            {

                while(pre(str[i]) <= pre(ope.top()))

                {

                    ans.push_back(ope.top());

                    ope.pop();

                }

                ope.push(str[i]);

            }

        }

        while(ope.top() != '=') //其余操作符存入后缀表达式中

        {

            ans.push_back(ope.top());

            ope.pop();

        }

        for(start = ans.begin(), end = ans.end(); start < end; ++start)

            printf("%c", *start);

        printf("\n");

    

    return 0;

}

 

你可能感兴趣的:(数据结构与算法)