1. 程式人生 > 其它 >資料結構-棧和佇列的應用(驗證括號的正確性,表示式求值,層次遍歷)

資料結構-棧和佇列的應用(驗證括號的正確性,表示式求值,層次遍歷)

技術標籤:資料結構佇列資料結構演算法c++

棧和佇列的應用

  棧的應用

  驗證括號的正確性

  題目很簡單就是輸入一串字元,判斷字元中的括號是否合法。直接上程式碼:

#include <iostream>
#include <string.h>
using namespace std;

typedef char ElemType;
#define MAXSIZE 100

typedef struct Stack
{
	ElemType data[MAXSIZE];
	int top;
}Stack;

void InitStack(Stack& S)
{ S.top = -1; } bool StackEmpty(Stack S) { if (S.top == -1) { return true; } return false; } bool Push(Stack& S, ElemType x) { if (S.top == MAXSIZE - 1) { return false; } S.top++; S.data[S.top] = x; return true; } bool Pop(Stack& S, ElemType& x) { if (S.top == -1) { return
false; } x = S.data[S.top]; S.top--; return true; } ElemType GetTop(Stack S) { return S.data[S.top]; } int main() { Stack S; InitStack(S); string str; cin >> str; //flag標誌狀態 true為括號匹配,false為不匹配 bool flag = true; for (int i = 0; i < str.size(); i++) { //元素若為{,(,[則入棧 if ((str[i]
== '{') || (str[i] == '[') || (str[i] == '(')) { Push(S, str[i]); }//元素若為},),]則出棧 賦值給right if ((str[i] == '}') || (str[i] == ']') || (str[i] == ')')) { if ((str[i] == '}' && GetTop(S) == '{') || (str[i] == ']' && GetTop(S) == '[') || (str[i] == ')' && GetTop(S) == '(')) { char top = Pop(S, top); continue; } else { Push(S, str[i]); } } } if (S.top != -1) { //當棧不為空時 flag = false; } if (flag == false) { cout << "括號不匹配!" << endl; } else cout << "括號匹配!" << endl; system("pause"); return 0; }

  實驗結果:

image-20210122155026920

image-20210122155116917

  表示式求值

  要求一個表示式的結果,例如 9 +(3 - 1) * 3 + 1 ,我們可以直接算出來,但是計算機不會,計算機一般將這種表示式轉換成字尾表示式,運算子在運算元後面,並且運算也是根據優先順序排列好的,沒有括號,利於計算機的計算,如上述表示式轉換為字尾表示式為:

9 3 1 - 3 * 10 + ,但是我們現在要實現的是中綴表示式的求值。計算思路:

  • 使用兩個棧,stack0用於儲存運算元,stack1用於儲存操作符
  • 從左往右掃描,遇到運算元入棧stack0
  • 遇到操作符時,如果優先順序低於或等於棧頂操作符優先順序,則從stack0彈出兩個元素進行計算,並壓入stack0,繼續與棧頂操作符的比較優先順序
  • 如果遇到操作符高於棧頂操作符優先順序,則直接入棧stack1
  • 遇到左括號,直接入棧stack1,遇到右括號,則直接出棧並計算,直到遇到左括號
//算符優先法
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;  
const int maxn=110; 
char priority[7][7]={ 
    {'>','>','<','<','<','>','>'},  
    {'>','>','<','<','<','>','>'},  
    {'>','>','>','>','<','>','>'},  
    {'>','>','>','>','<','>','>'},  
    {'<','<','<','<','<','=','0'},   // 此行"("=")"表示左右括號相遇,括號內運算已完成 
    {'>','>','>','>','0','>','>'},  
    {'<','<','<','<','<','0','='}    // "=" 表示整個表示式求值完畢 
	};                               //  "0"表示不可能出現這種情況 ( 語法錯誤 ) 
	
//Precede 用於判斷運算子棧棧頂運算子 a1 與讀入運算子 a2 之間的優先關係函式 
char Procede(char a,char b){   // 建立 pre[][] 到 運算子間的對映關係 
    int i,j;  
    switch(a){  
        case'+':i=0;break;  
        case'-':i=1;break;  
        case'*':i=2;break;  
        case'/':i=3;break;  
        case'(':i=4;break;  
        case')':i=5;break;  
        case'#':i=6;break;   // # 是表示式的結束符 
    }  
    switch(b){  
        case'+':j=0;break;  
        case'-':j=1;break;  
        case'*':j=2;break;  
        case'/':j=3;break;  
        case'(':j=4;break;  
        case')':j=5;break;  
        case'#':j=6;break;  
    }  
    return priority[i][j];  
}
     
int Operate(int m,int n,char x){  
    if(x=='+')  
    return m+n;  
    if(x=='-')  
    return n-m;  
    if(x=='*')  
    return m*n;  
    if(x=='/')  
    return n/m;  
}  
// EvaluuateExpression-reduced
int main(){
    stack <int> OPND;  // Operand stack
    stack <char> OPTR;  // Operator stack
	OPTR.push('#');//
    char ss[2]="#";//尾部有\0 
    char s[maxn];
    cin>>s;
    strcat(s,ss);// 運算式尾部加 "#"--結束運算子 
    char c=s[0];
    int k=1;
    while(c!='#'||OPTR.top()!='#'){  //表示式未讀完或者運算未完 
        int y=0;  
        if(c>='0'&&c<='9'){    
            while(c>='0'&&c<='9'){  // 讀入連續的數字 
                y=y*10+(c-'0');  
                c=s[k++];  
            }  
            OPND.push(y);  // 把讀進的數字入數字棧 
        }
        else{
            switch(Procede(OPTR.top(),c))  
            {  
                case'<':  //棧頂元素優先權低 
                    OPTR.push(c);  
                    c=s[k++];  
                    break;  
                case'=':  
                    OPTR.pop();  // 脫括號 
                    c=s[k++];  // 讀入下一個字元 
                    break;  
                case'>':  //退棧並將運算結果入棧 
                    char x=OPTR.top();OPTR.pop();  
                    int m=OPND.top();OPND.pop();  
                    int n=OPND.top();OPND.pop();  
                    OPND.push(Operate(m,n,x));  
                    break;    
            } 
        }
    }
    cout<<OPND.top();
    return 0;
}

  實驗結果:

image-20210122155312932

  佇列的應用

  層次遍歷

  利用佇列儲存每一層的結點,再儲存到陣列中,很容易理解。下面是套路:

vector<vector<int>> levelOrder(TreeNode* root) {
    queue<TreeNode*> q;
    if (root != nullptr)   q.push(root);
    vector<vector<int>> res;
    while (!q.empty()) {
        int sz = q.size();
        vector<int> temp;
        for (int i = 0; i < sz; i++) {
            TreeNode* cur = q.front();
            q.pop();
            temp.push_back(cur->val);
            if (cur->left != nullptr)
                q.push(cur->left);
            if (cur->right != nullptr)
                q.push(cur->right);
        }
        res.push_back(temp);
    }
    return res;
}

  佇列在計算機系統中的應用

  一、解決主機與外部裝置之間速度不匹配的問題。

  二、解決由多使用者引起的資源競爭問題。

如果覺得本文對你有幫助的話,不妨關注作者一波,小小的關注其實對我很重要。更多高質量內容與資料請訪問:資料結構簡單學,個人主頁:修心的小屋
如果喜歡的話,不妨關注一波,謝謝啦。
在這裡插入圖片描述