棧:
【引出棧的概念】
問題場景:括號是否合法,成對出現的?
()正確
(())正確
())錯誤
()))錯誤
問題抽象:
輸入項:一個字符串,裏面含有一堆括號。
輸出項:YES/NO,括號是否是成對出現的。
處理過程:每輸入一個字符串,就判斷這個字符串的中間是否存在某個位置,左括號的數量比右括號少。如果存在這樣的一個位置,則返回NO,如果處理到末尾,左括號的數量不匹配,也返回NO,否則返回YES。
#include <string>
#include <iostream>
using namespace std;
bool judge_one(string seq)
{
uint32_t left_nums = 0, right_nums = 0;
for(uint32_t i=0;i<seq.length();i++)
{
if (seq[i] == '(')
{
left_nums++;
}
else if (seq[i]==')')
{
right_nums++;
}
if (left_nums < right_nums)
{
return false;
}
}
if (left_nums != right_nums)
{
return false;
}
else
{
return true;
}
}
int main(int argc,char* argv[])
{
bool result;
result=judge_one("((((((())))())");
cout << result << endl;
return 0;
}
上面的代碼是否能夠優化呢?
主要思路:right_num是否一定需要呢?答案是不用,我們可以把左括號爲+1,右括號爲-1做替代。bool judge_one_2(string seq)
{
uint32_t nums = 0;
for (uint32_t i = 0; i<seq.length(); i++)
{
if (seq[i] == '(')
{
nums++;
}
else if (seq[i] == ')')
{
nums--;
}
if (nums < 0)
{
return false;
}
}
if (nums != 0)
{
return false;
}
else
{
return true;
}
}
思考:
1) +1可以等價爲:進,-1可以等價爲出
2) 一對()可以等價爲一個完整的事件(和值爲0的事件,比如公交車上去一個人下來一個人和值爲0)
3) (())可以看做事件與事件之間的完全包含關係,也就是先要解決問題B才能解決數據A
4) 以上思維,就得到了新的數據結構(棧),它可以用來處理具有完全包含關係的事件。(事件的定義:和值爲零,有發生必然有結束。完全包含的事件:就像3)表示的括號,要解決最外面的事件必須先解決最裏面一層。)
【棧的定義】
棧是一種後進先出的數據結構,可以用來處理時間之間具有完全包含關係的問題。
- 有一個指針TOP,指向棧頂元素
- 入棧,先將TOP+1,然後將新元素放到TOP所指位置
- 出棧,先判TOP?<0,夫走TOP-1
用棧完成這個工作:
bool judge_one_3(string seq)
{
stack<char> data_stack;
for (uint32_t i = 0; i < seq.length(); i++)
{
if (seq[i] == '(') data_stack.push('(');
else if (seq[i] == ')' && data_stack.empty()) return false;
else if(seq[i]==')') data_stack.pop();
}
if (!data_stack.empty()) return false;
return true;
}
結論:
以上就用了教科書裏面常用的例子引出了棧的概念以及棧的使用場景。
參考
小象《算法基礎》課程