内容概览及预备知识:
预备知识:栈与队列:
STL基本的栈操作(stack):

1 #include <iostream> 2 using namespace std; 3 4 #include <stack> 5 int main(){ 6 stack <int> stk; 7 if(stk.empty()){ //判断是否为空 isempty() 8 cout <<"The Stack is empty!!!"<<endl; 9 } 10 stk.push(5); //压栈 11 stk.push(6); 12 stk.push(10); 13 14 cout <<"The Stack' top is " <<stk.top()<<endl; 15 stk.pop(); //弹出栈顶 16 stk.pop(); 17 cout <<"The Stack' top is "<<stk.top()<<endl; 18 cout <<"The Stack' size is "<<stk.size()<<endl; //栈中的size 19 20 return 0; 21 }
STL基本的队列操作(queue):

1 #include <iostream> 2 using namespace std; 3 4 #include <queue> 5 int main(){ 6 queue <int> quu; 7 if(quu.empty()){ 8 cout << "The Queue is empty!"<<endl; 9 } 10 quu.push(5); //加入队列 11 quu.push(6); 12 quu.push(10); 13 14 cout<<"The Queue' front is "<<quu.front()<<endl; 15 quu.pop(); //从队列头拿出 16 quu.pop(); 17 cout<<"The Queue' front is "<<quu.front()<<endl;//队头 18 quu.push(1); //队列后加入 1 19 cout<<"The Queue' back is "<<quu.back()<<endl; //队尾 20 21 22 cout<<"The Queue' size is "<<quu.size()<<endl; //队列的大小 23 24 return 0; 25 }
例1:使用队列实现栈 (No.225):
思路及代码:
假设前4个已经调整好了,下面是如何调整第五个!!!
代码:

1 class MyStack{ 2 public: 3 MyStack(){} 4 void push(int x){ 5 queue <int> temp_queue; //临时队列 6 temp_queue.push(x); 7 while(!_data.empty()){ //将_data中的数据push 到临时队列 8 temp_queue.push(_data.front()); 9 _data.pop(); 10 } 11 while(!temp_queue.empty()){ //将 temp_queue中重新放入到_data中 12 _data.push(temp_queue.front()); 13 temp_queue.pop(); 14 } 15 } 16 17 int pop(){ 18 int x = _data.front(); 19 _data.pop(); 20 return x; 21 } 22 23 int top(){ 24 return _data.front(); 25 } 26 27 bool empty(){ 28 return _data.empty(); 29 } 30 private: 31 queue <int> _data; // _data中存储的是 栈存储的顺序 32 };

1 #include <iostream> 2 using namespace std; 3 4 #include <queue> 5 6 class MyStack{ 7 public: 8 MyStack(){} 9 void push(int x){ 10 queue <int> temp_queue; //临时队列 11 temp_queue.push(x); 12 while(!_data.empty()){ //将_data中的数据push 到临时队列 13 temp_queue.push(_data.front()); 14 _data.pop(); 15 } 16 while(!temp_queue.empty()){ //将 temp_queue中重新放入到_data中 17 _data.push(temp_queue.front()); 18 temp_queue.pop(); 19 } 20 } 21 22 int pop(){ 23 int x = _data.front(); 24 _data.pop(); 25 return x; 26 } 27 28 int top(){ 29 return _data.front(); 30 } 31 32 bool empty(){ 33 return _data.empty(); 34 } 35 private: 36 queue <int> _data; // _data中存储的是 栈存储的顺序 37 }; 38 39 40 41 int main(){ 42 MyStack * stk = new MyStack(); 43 stk->push(2); 44 stk->push(4); 45 stk->push(8); 46 int a = stk->pop(); 47 int b = stk->top(); 48 bool c = stk->empty(); 49 cout <<a <<b<<c<<endl; 50 51 return 0; 52 }
例2:使用栈实现队列 (No.232):
思路及代码:
和例1一样,先假设已经有了四个元素,现在准备插入第五个元素,就是如何将5 放到栈的最下面!!!

1 class MyQueue{ 2 public: 3 MyQueue(){} 4 void push(int x) { 5 //先将原有的栈中元素都出栈 进入临时栈中 temp_stk 6 stack <int> temp_stk; 7 while(!_data_stk.empty()){ 8 temp_stk.push(_data_stk.top()); 9 _data_stk.pop(); 10 } 11 _data_stk.push(x); //将要加入的放到临时栈中 12 while(!temp_stk.empty()){ //最后再将临时中的元素全部转回到data_stack中 13 _data_stk.push(temp_stk.top()); 14 temp_stk.pop(); 15 } 16 } 17 18 int pop(){ 19 int x = _data_stk.top(); 20 _data_stk.pop(); //返回类型是void 21 return x; 22 } 23 int peek(){ //front 24 return _data_stk.top(); 25 } 26 bool empty(){ 27 return _data_stk.empty(); 28 } 29 30 private: 31 stack <int> _data_stk; 32 };

1 #include <iostream> 2 using namespace std; 3 4 #include <stack> 5 6 class MyQueue{ 7 public: 8 MyQueue(){} 9 void push(int x) { 10 //先将原有的栈中元素都出栈 进入临时栈中 temp_stk 11 stack <int> temp_stk; 12 while(!_data_stk.empty()){ 13 temp_stk.push(_data_stk.top()); 14 _data_stk.pop(); 15 } 16 _data_stk.push(x); //将要加入的放到临时栈中 17 while(!temp_stk.empty()){ //最后再将临时中的元素全部转回到data_stack中 18 _data_stk.push(temp_stk.top()); 19 temp_stk.pop(); 20 } 21 } 22 23 int pop(){ 24 int x = _data_stk.top(); 25 _data_stk.pop(); //返回类型是void 26 return x; 27 } 28 int front(){ //peek() 29 return _data_stk.top(); 30 } 31 bool empty(){ 32 return _data_stk.empty(); 33 } 34 35 private: 36 stack <int> _data_stk; 37 }; 38 39 40 int main(){ 41 42 return 0; 43 }
注:例1 和例2 的时间复杂度都是O(n) 的。
例3:包含min函数的栈(No.155):
注:这里要求时间复杂度为 O(1)
思路及代码:
因为时间复杂度是O(1),所以肯定不能通过遍历等完成,
思考:要用1个变量记录最小值?
所 下:
最终的思路如下:

1 class MinStack{ 2 public: 3 //构造函数 4 MinStack(){} 5 //将元素x压入栈中 6 void push(int x){ 7 stk_data.push(x); 8 if(stk_min.size()==0){ 9 stk_min.push(x); 10 }else if(x >= stk_min.top()){ 11 stk_min.push(stk_min.top()); 12 }else{ 13 stk_min.push(x); 14 } 15 } 16 //将栈顶元素弹出 17 void pop(){ 18 stk_data.pop(); 19 stk_min.pop(); 20 } 21 //返回栈顶元素 22 int top(){ 23 return stk_data.top(); 24 } 25 //返回栈内的最小元素 26 int getMin(){ 27 return stk_min.top(); 28 } 29 private: 30 stack <int> stk_data; 31 stack <int> stk_min; 32 };
例4:合法的出栈序列(poj.1363):
原题介绍和 POJ介绍:
思路及代码:
思考:模拟入栈过程:
现在要检测 3 2 5 4 1 是否合法?
这时3 就和队列中的第一个相等了,此时栈和队列同时进行弹出操作!
继续对比!
最后栈中的元素为空,所以说明合法,否则是不合法的!
下面是个不合法序列的举例:
虽然它是有两个循环,但是它整体的时间复杂度还是O(n) ,因为每个元素 都是入栈一次和出栈一次!

1 bool check_is_valid_order(queue<int> &que_order){ 2 stack <int> stk; //模拟栈 3 int n = que_order.size(); 4 for (int i = 0; i < n; ++i) { 5 stk.push(i+1); 6 while (!stk.empty() &&stk.top() == que_order.front()){ 7 stk.pop(); 8 que_order.pop(); 9 } 10 } 11 if(!stk.empty()){ //当stk 模拟战不是空的时候,说明不合法 12 return false; 13 } 14 return true; 15 }
POJ的提交:

1 #include <iostream> 2 using namespace std; 3 4 #include <stack> 5 #include <queue> 6 bool check_is_valid_order(queue<int> &que_order){ 7 stack <int> stk; //模拟栈 8 int n = que_order.size(); 9 for (int i = 0; i < n; ++i) { 10 stk.push(i+1); 11 while (!stk.empty() &&stk.top() == que_order.front()){ 12 stk.pop(); 13 que_order.pop(); 14 } 15 } 16 if(!stk.empty()){ //当stk 模拟战不是空的时候,说明不合法 17 return false; 18 } 19 return true; 20 } 21 22 23 int main(){ 24 int n; 25 int train; 26 scanf("%d",&n); 27 while(n){ 28 scanf("%d",&train); 29 while(train){ 30 queue <int> order; 31 order.push(train); 32 for (int i = 1; i < n; ++i) { 33 scanf("%d",&train); 34 order.push(train); 35 } 36 if(check_is_valid_order(order)){ 37 cout<<"Yes"<<endl; 38 }else{ 39 cout<<"No"<<endl; 40 } 41 scanf("%d",&train); 42 } 43 cout<<endl; 44 scanf("%d",&n); 45 } 46 return 0; 47 }
例5:简单的计算器(No.224 leetcode ):
思路及代码:
下面是没有优先级(无括号)和有优先级(有括号)的对比
下面是一个例子来说明思路!!!
下面的问题是字符串如何转换成数字?
计算函数:

1 void compute(stack <int> & number_stk,stack <char>& char_stk){ 2 if(number_stk.size() <2){ 3 return; 4 } 5 int num2 = number_stk.top(); 6 number_stk.pop(); 7 int num1 = number_stk.top(); 8 number_stk.pop(); 9 if(char_stk.top() == '+'){ 10 number_stk.push(num1+num2); 11 }else if(char_stk.top() == '-'){ 12 number_stk.push(num1-num2); 13 } 14 char_stk.pop(); 15 }
下面是最重要的字符串处理的思路:
状态机!!!

1 void compute(stack <long> & number_stk,stack <char>& operation_stk){ 2 if(number_stk.size() <2){ 3 return; 4 } 5 long num2 = number_stk.top(); 6 number_stk.pop(); 7 long num1 = number_stk.top(); 8 number_stk.pop(); 9 if(operation_stk.top() == '+'){ 10 number_stk.push(num1+num2); 11 }else if(operation_stk.top() == '-'){ 12 number_stk.push(num1-num2); 13 } 14 operation_stk.pop(); 15 } 16 17 class Solution{ 18 public: 19 long calculate(string s){ 20 static const int STATE_BEGIN =0; 21 static const int NUMBER_STATE =1; 22 static const int OPERATION_STATE =2; 23 24 stack <long> number_stk; 25 stack <char> operation_stk; 26 27 long number =0; 28 int STATE = STATE_BEGIN; 29 int compuate_flag = 0; 30 for (int i = 0; i < s.length(); ++i) { 31 if(s[i] == ' '){ //如果第一个字符是空格 32 continue; 33 } 34 switch(STATE){ 35 case STATE_BEGIN: 36 if(s[i] >='0' && s[i] <='9'){ 37 STATE = NUMBER_STATE; 38 }else{ 39 STATE = OPERATION_STATE; 40 } 41 //i 指针回退操作 42 i -- ; 43 break; 44 case NUMBER_STATE: 45 if(s[i] >='0' && s[i] <='9') { 46 number = 10*number + s[i] -'0'; 47 }else{ 48 number_stk.push(number); //将算好的number push到栈中 49 if(compuate_flag == 1){ 50 compute(number_stk,operation_stk); 51 } 52 number = 0; 53 i--; 54 STATE = OPERATION_STATE; 55 } 56 break; 57 case OPERATION_STATE: 58 if(s[i] == '+' || s[i] == '-'){ 59 operation_stk.push(s[i]); 60 compuate_flag = 1; //当遇到 + / - 时候 为1 61 }else if(s[i] == '('){ 62 // 遇到 ( 63 STATE = NUMBER_STATE; 64 compuate_flag = 0; 65 }else if(s[i]>='0' && s[i] <='9'){ 66 i--; //当仍然遇到的是数字时候。 回退 67 STATE = NUMBER_STATE; 68 }else if(s[i] == ')'){ 69 compute(number_stk,operation_stk); //计算最后一步 70 } 71 break; 72 } 73 74 } //for 75 if(number != 0){ //1+2+3 就会剩一个number = 3 76 number_stk.push(number); 77 compute(number_stk,operation_stk); 78 } 79 if(number==0 && number_stk.empty()){ 80 return 0; //例如给定字符串 “” 81 } 82 return number_stk.top(); 83 } 84 };

1 #include <iostream> 2 using namespace std; 3 4 #include <stack> 5 #include <queue> 6 7 void compute(stack <int> & number_stk,stack <char>& operation_stk){ 8 if(number_stk.size() <2){ 9 return; 10 } 11 int num2 = number_stk.top(); 12 number_stk.pop(); 13 int num1 = number_stk.top(); 14 number_stk.pop(); 15 if(operation_stk.top() == '+'){ 16 number_stk.push(num1+num2); 17 }else if(operation_stk.top() == '-'){ 18 number_stk.push(num1-num2); 19 } 20 operation_stk.pop(); 21 } 22 23 class Solution{ 24 public: 25 long calculate(string s){ 26 static const int STATE_BEGIN =0; 27 static const int NUMBER_STATE =1; 28 static const int OPERATION_STATE =2; 29 30 stack <int> number_stk; 31 stack <char> operation_stk; 32 33 int number =0; 34 int STATE = STATE_BEGIN; 35 int compuate_flag = 0; 36 for (int i = 0; i < s.length(); ++i) { 37 if(s[i] == ' '){ //如果第一个字符是空格 38 continue; 39 } 40 switch(STATE){ 41 case STATE_BEGIN: 42 if(s[i] >='0' && s[i] <='9'){ 43 STATE = NUMBER_STATE; 44 }else{ 45 STATE = OPERATION_STATE; 46 } 47 //i 指针回退操作 48 i -- ; 49 break; 50 case NUMBER_STATE: 51 if(s[i] >='0' && s[i] <='9') { 52 number = 10*number + s[i] -'0'; 53 }else{ 54 number_stk.push(number); //将算好的number push到栈中 55 if(compuate_flag == 1){ 56 compute(number_stk,operation_stk); 57 } 58 number = 0; 59 i--; 60 STATE = OPERATION_STATE; 61 } 62 break; 63 case OPERATION_STATE: 64 if(s[i] == '+' || s[i] == '-'){ 65 operation_stk.push(s[i]); 66 compuate_flag = 1; //当遇到 + / - 时候 为1 67 }else if(s[i] == '('){ 68 // 遇到 ( STATE_BEGIN 69 // STATE = STATE_BEGIN; 70 STATE = NUMBER_STATE; //它不能解决两个 (( 在一起 的情况,上面的可以解决。 71 compuate_flag = 0; 72 }else if(s[i]>='0' && s[i] <='9'){ 73 i--; //当仍然遇到的是数字时候。 回退 74 STATE = NUMBER_STATE; 75 }else if(s[i] == ')'){ 76 compute(number_stk,operation_stk); //计算最后一步 77 } 78 break; 79 } 80 81 } //for 82 if(number != 0){ //1+2+3 就会剩一个number = 3 83 number_stk.push(number); 84 compute(number_stk,operation_stk); 85 } 86 if(number==0 && number_stk.empty()){ 87 return 0; //例如给定字符串 “” 88 } 89 return number_stk.top(); 90 } 91 }; 92 93 94 int main(){ 95 string s = "1 -((1+10))"; 96 Solution * solve = new Solution(); 97 cout << solve->calculate(s); 98 return 0; 99 }
堆方面:
预备知识:二叉堆属性
例6:(No. ):
思路及代码:
例7:(No. ):
思路及代码:
例8:(No. ):
思路及代码: