The stack structure must be understood in combination with specific application scenarios. . .
Mainly refer to Deng Junhui's data structure course, based on c++ implementation.
a basic concept
The stack is a restricted sequence: insertions and deletions can only be done at the top of the stack, and the bottom of the stack is the blind end.
Features: first in, last out (FILO), last in first out (LIFO)
Basic interface: size() / empty()
push() on the stack
pop() pops the stack
top() check the top
Extended interface: getMAX()...
Basic implementation:
Stacks are also a special case of sequences, so they can be derived from vectors or lists
1 template <typename> class Stack :: public Vector<T> { // Stack template class derived from vector 2 3 public: // size(), empty() and other open interfaces can be used directly 4 void push(T const &e) {insert(size(),e);} // Push 5 T pop() { return remove(size() - 1 );} // Push 6 T &top() { return (* this ) [size()- 1 ];} // take the top 7 }
The realization of the above- mentioned three basic interfaces only needs O(1) time.
Two application scenarios
When are stacks used? Two conditions need to be met: 1. The state needs to be saved; 2. The state output has a sequence
Typical applications
Reverse order output: The output order is reversed with the processing process; the recursion depth and output length are not easy to predict. Example: base conversion
Delayed buffering: In the linear scan algorithm mode, the processable prefixes are not determined until the read-ahead is long enough. Example: Bracket Matching
Three examples
1. Base conversion
Algorithm implementation
1 void convert( Stack< char > & S,_int64 n, int base ) { 2 static char digit[] = // The digit symbol in the new system can be appropriately expanded according to the value range of base 3 { ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , '9' , ' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' }; 4 while (n > 0 ) { // From low to high, calculate the new base one by one Each digit 5 S.push(digit[n % base ]); // The remainder (the current digit) is pushed onto the stack 6 n /= base ; // n is updated to the division quotient of base 7 } 8 9 } 10 main( ) { 11 Stack< char > S; convert( S, n, base ); // Use the stack record to convert each digit 12 while ( !S.empty()) printf( " %c " , S.pop()); // output 13 in reverse order }
2. Bracket matching
Algorithm implementation
1 bool paren( const char exp[], int lo, int hi) { // exp[lo,hi) 2 Stack< char > S; // use the left parenthesis found but not matched by the stack record 3 for ( int i = lo; i < hi; i++) // Check current characters one by one 4 if ( ' ( ' == exp[i]) S.push( exp[i] ); // In case of left parenthesis, push into stack 5 else if ( !S.empty()) S.pop(); // When the right parenthesis is encountered, if the stack is not empty, the left parenthesis will be popped 6 else return false ;// Otherwise the stack is empty, the parentheses do not match 7 return S.empty(); // Finally, if and only if the stack is empty 8 9 10 }
Four stack shuffle
Total number of shuffles: SP(n) = (2n)! / (n+1)! / (n)!
Shuffle permutations without "forbidden shapes" are legal. The original arrangement is <...i <j<k...], the shuffled arrangement is [...k,....,i,....,j....,....> This is "forbidden".