Stack and Queue
1. Stack stack
Stack is a special data structure. It has the same logical structure as linear tables, but its operation has more restrictions, that is, it can only put data from one end and read data from one end. One end of the stack accesses data called top of stack, while the bottom of the stack does not allow any access. Remove the top element of the stack (top of stack)This operation is called pop, the operation of storing elements is called push, and when the stack is empty it is called an empty stack.
Lift up a plain chestnut: After we wash the dishes, we stack them one by one. Naturally, we put the bottom bowl first, and then we can continue to put the bowl on top. When we pick up the bowl, we also take the top bowl first, and then the bottom bowl.
The stack is characterized by LIFO. As for the specific implementation of the stack, we can write our own. The easiest way to do this is to use an array and push and pop elements only at the end of the array. Of course, the most common STL library that calls C++ is the STL library, which contains the encapsulated stack data type, making it easier to use.
2. queue
Queue is another linear table that defines access locations. It only allows data push es to be stored in a section of the queue and only data pop s to be taken out at the other end of the queue. The end of the allowed insertion is called the end of the queue and the end of the allowed extraction is called the head of the queue.
Lift up a plain chestnut: A queue of people in the dining room is of high quality. Every time a person automatically stands at the end of the queue, the person in the queue plays first, then leaves the queue. This first-in-first-out data structure is called a queue.
2. Application
1.stack conversion
A number is converted from 10 to 2 by dividing the number by 2 until the remainder is 0. The inverted output of all quotient operations is the final answer. Because this calculation is done from low to high bit one by one, but the output is from high to low bit. Stack is needed to implement this.
#include <stdio.h> #include <stack> using namespace std; int main() { int x; printf("Please enter a decimal number:"); scanf("%d", &x); int tmp = x; stack<int>n; while (tmp != 0) { n.push(tmp % 2); tmp /= 2; } printf("%d Binary is ", x); while (!n.empty()) { printf("%d", n.top()); n.pop(); } printf("\n"); }
2.stack bracket matching
There are many parentheses in a string of formulas. The problem we need to face is:
- Is parentheses legal in this formula: (1+2)?
- Plus parentheses, how should the priority of an arithmetic be considered
Here we start with the first problem, which is bracket matching.
Scan the arithmetic from left to right and let it go on the stack whenever the left bracket'('is encountered. If the right bracket')' is encountered, there are two situations to consider: if the stack is empty, exit the program after a direct error. If the stack is not empty, look at the top of the stack, and if the top of the stack is left bracket'('), throw the left bracket'(', if the top of the stack is right bracket')', the current read right parenthesis is pushed into the stack.
Specific code implementation is given in the next section.
3. Expression calculation and priority handling (suffix to suffix)
Earlier, we already know how to match brackets. However, when evaluating expressions, we also need to consider the precedence of operators.
- Addition, Subtraction, Mu lt iplication, Division, Power
- When the symbol priority is the same, the operator that appears first from left to right takes precedence. (The power operation is special, so be careful not to follow this rule, you may consider a b c a^{b^c} abc, that is, B and C combine first)
Based on the above considerations, we have the following ideas:
Open two stacks, shapes stores letters, opt stores operators. Push numbers into shapes, and operators into opt. If the precedence of the currently read operator is lower than that of opt top, opt exits the stack and two letters from shapes participate in the operation until the top priority of OPT is lower or empty than that of the currently read operator, and then it willThe current operator push.
Note: Left parentheses have the highest priority outside the stack and the lowest once they enter the stack.
#include <stdio.h> #include <string.h> #include <stack> using namespace std; char operation[100000]; stack<char>x; int compare_opt(char a, char b) {//If negative number, a priority is lower than b, if positive number, a priority is higher than B int x, y; if (a == '+' || a == '-') x = 1; else if (a == '^')x = 3; else if (a == '(')x = 0; else x = 2; if (b == '*' || b == '/')y = 2; else if (b == '^')y = 10; else if (b == '(')y = 0; else y = 1; return x - y; } int main() { int N; scanf("%d", &N); getchar(); while (N) { gets(operation); int len = strlen(operation); for (int i = 0; i < len - 1; i++) { if ((operation[i] <= 'z' && operation[i] >= 'a') || (operation[i] <= 'Z' && operation[i] >= 'A')) { //What you are reading is a letter printf("%c", operation[i]); } else { //What you are reading is an operator //First determine if it is a special operator if (operation[i] == '(') { x.push(operation[i]); } else if (operation[i] == ')') { //Right parenthesis encountered while (x.top() != '(') { printf("%c", x.top()); x.pop(); } x.pop(); } else { //General Operators if (x.empty()) { x.push(operation[i]); } else { while (!x.empty() && compare_opt(x.top(), operation[i]) >= 0) { if (operation[i] == '^' && compare_opt(x.top(), operation[i]) == 0)break;//Notice the special nature of the power operation printf("%c", x.top()); x.pop(); } x.push(operation[i]); } } } } while (!x.empty()) { printf("%c", x.top()); x.pop(); } printf("\n"); N--; } }
4.queue output Yang Hui Triangle Line
In computers, queues are often used to solve problems that require progressive processing. Yang Hui's triangular rows are a typical example of hierarchical processing. The numbers in each row of Yang Hui's triangular rows correspond to binomials
(
a
+
b
)
i
(a+b)^i
(a+b)i Expand the coefficients of each item.
One of the properties of Yang Hui's triangle line is that the numbers in its line I correspond to the sum of the two corresponding numbers in its line i-1. We can use a queue to process this hierarchy layer by layer. The code is as follows
#include <stdio.h> #include <queue> using namespace std; int main() { int n; int x = 0, y; queue<int>que; scanf("%d", &n); //Two coefficients of the first row are pre-queued que.push(1);que.push(1); for (int i = 1; i < n; i++) { printf("\n"); que.push(0); for (int j = 1; j <= i + 2; j++) { y = que.front(); que.pop(); que.push(x + y); x = y; if (j != i + 2)printf(" %d", x); } } }
5. Use stack to change recursive process to non-recursive process
Start with a recursive classic, the Hannotta problem.
#include <stdio.h> void Hanoi(int n, char A, char B, char C) { //There are n plates, moving from A to C with B if (n == 1) printf("Move disk from %c to %c.\n", A, C); else { Hanoi(n - 1, A, C, B);//Move n-1 plates on A through C to B printf("Move disk from %c to %c.\n", A, C); Hanoi(n - 1, B, A, C);//Stack just moved B on C through A } } int main() { int n; scanf("%d", &n); Hanoi(n, 'A', 'B', 'C'); }
The idea of dividing and conquering is used here. By dividing the movement of N plates into one (pack n-1 as one) and another, the problem of solving size n is broken into two problems of size n-1. Based on this top-down, layer-by-layer decomposition principle, a recursive algorithm is designed.
However, a little analysis reveals that the time complexity of this algorithm is
O
(
n
2
)
O(n^2)
O(n2), proportional to the square of the recursion depth. Also, since recursive calls require calls to the recursive workstack to hold local variables for each round of recursion, the spatial complexity is
O
(
n
)
O(n)
O(n).
This is awesome. So we want to use the stack to make it non-recursive, and we want to optimize its space-time complexity.