The software world is a projection of the real world.
introduction
Most of the concepts in the software world are not created out of thin air. Most of these concepts are abstracted from the real world. Just like the "stack" discussed in this article, there are also models in daily life, such as stacks of bowls, and the first placed first is placed at the bottom, like the following:
This is the opposite of queuing. A data structure corresponding to queuing, we call it a queue. In fact, the data structure of the stack is still very commonly used in daily use, such as undo operation, which is a universally built-in operation in the software, just like we have made some changes in daily coding, and we want to go back to the previous step. Generally, use ctrl + z. The software records your operation or input by time, like the following:
The one with the highest time is at the bottom, so that we can take regret medicine. For example, if we write the parentheses matching in the code, if one is missing, how does the compiler know? Let's analyze this problem:
The number is the entry order of the parentheses. Each right parenthesis will match the unmatched left parenthesis encountered recently, that is, "last in first out, or first in last out".
Experience the above, each right parenthesis will match the unmatched left parenthesis encountered recently. We use p to record the latest position of the left parenthesis, use q to point to the currently newly entered parenthesis, compare p and q, and if they match, delete the left parenthesis, and p back one place. If there is a left parenthesis at the end of the match, then the parenthesis is not matched.
Another example is that our commonly used functions call each other. Java always starts with a main function. If our code is that the main method calls the a method, the a method calls the c method, and the c method calls the d method, then the obvious is d After the method is executed, the c method is executed, and the c method is executed before the a method is executed. This execution model is also very similar to a stack:
Carefully experience the above use cases. The common feature of these problems is that they have the characteristics of "last in, first out" in the process. This is a typical problem, and we abstract it out as the "stack" model in the data structure. Let's start to explain some concepts of the stack and some basic applications.
Stack
Overview
The following is a schematic diagram of the stack:
You can understand the rectangular parallelepiped in the schematic diagram as a bamboo tube, with the top open and the bottom closed. Inside are small balls with numbers written in them. The order of placing them depends on the order of the balls, from small to large. If we want to take the ball from the bamboo tube, we can find a rule: the first put in can only be taken out later; on the contrary, the small ball put in later can be taken out first, that is, first in and out. This is a typical stack. Features.
When we abstract the ball in the above structure as a node in the data structure, because the relationship between the nodes is linear, it also belongs to a linear table, and because its operations can only be performed on the same end, it It is a linear table with limited operations. We call this type of linear table a stack.
Now we give the definition of the stack: A stack is a special linear table, all of its insertions and deletions are restricted to the same end of the table. The section of the stack that allows insert and delete operations is called the top of the stack, and the other end is called the bottom of the stack. When there are no elements in the stack, it is called an empty stack
The insertion operation in the stack is usually called push, push or push (PUSH), and the delete operation of the stack is usually called push and pop.
The first element pushed onto the stack is at the bottom of the stack, the last element pushed onto the stack is at the top of the stack, the first element pushed out of the stack is the top element of the stack, and the last element pushed out of the stack is the bottom element of the stack.
Some people might think why we need to introduce a stack, or just use arrays and linked lists to implement the stack? Why do we need to draw a special data structure? In principle, the queues, trees, and graphs we will talk about later are also implemented by arrays and linked lists. Each data structure corresponds to a specific type of data processing problem, such as stacks. Specially deal with "first-in-last-out", while also simplifying the program design ideas and narrowing the scope of our thinking. Even if an array is used to implement the stack, we have to let external callers not worry about subscript out-of-bounds and increase or decrease. Then this is a new kind of array, but we are used to calling it a stack.
Similar to the linear table, the basic operations of the stack are as follows:
- Stack initialization operation: create an empty stack table
- The stack is empty: judge whether the stack is empty
- Take the top element of the stack: take the value of the top element of the stack
- Push stack: Insert element e into stack S, making it the new top element
- Pop stack: delete the element of stack S.
Many current high-level languages, such as Java and C#, have built-in encapsulation of the stack data structure. We can directly use the push and pop operations on the stack without paying attention to the implementation details of the stack. At the same time, design ideas can also be used for reference.
We call stacks implemented with arrays as sequential stacks, and stacks implemented with linked lists are generally called chain stacks. In fact, the sequential stack can also be subdivided. One is to set the size of the stack at the beginning, and when the stack exceeds the size, we can choose to call the last element at the bottom of the stack as the bottom element. The second type is called dynamic stack. The size of the stack is dynamic, that is, dynamic expansion. When the upper limit of the stack is exceeded, the capacity is automatically expanded. The size of the stack basically depends on the size of the memory.
Sequential stack
We try to use arrays to implement the following sequential stacks. In fact, the design related to sequential stacks can also refer to related design ideas in Java. Let's look at Stack in Java:
The operation is also consistent with what we discussed above. What is the difference between peek and pop:
- peek takes the top element of the stack without deleting it
- pop takes the element at the top of the stack, deletes and returns the element at the top of the stack
The design idea of Stack in Java: - The stack is empty to see the actual capacity of the array
- The push operation adds elements to the end of the array
- The peek operation returns the last element of the array
The pop operation returns the last element of the array, and the top element of the stack moves one position back
We can also let the sequence stack we built inherit our data structure and algorithm analysis (3) Linear list SequenceList, so that we don't need to rewrite the expansion operation, just use the method of implementing the stack. Regarding the design of the method, we can fully learn from Stack in Java:public class SequenceStack extends SequenceList { public SequenceStack() { } public int push(int data){ add(data); return data; } /** * 返回数组的最后一个元素, 同时栈顶元素向后移动一个位置 * @return */ public int pop(){ if (size() == 0){ // 抛出异常 } int data = peek(); remove(size() - 1); return data; } public int peek(){ if (size() == 0){ // 抛出异常 } return get(size() - 1); } public boolean empty(){ return size() == 0; } }
Chain stack
We call stacks that use chain storage as chain stacks or chain stacks. The chain stack is composed of nodes, and each node contains two parts: data field and pointer field. In the chain stack, the storage area of each node is used to store each element in the stack, and the pointer field is used to represent the relationship between the elements. Like the following:
public class LinkedStack { private Node top; //指向栈顶元素 private class Node{ private int data; private Node next; public Node(int data , Node next){ this.data = data; this.next = next; } public int getData() { return data; } public Node getNext() { return next; } } public LinkedStack() { } /** * @param data * @return */ public int push(int data){ Node node = new Node(data,top); top = node; return data; } public int pop(){ return peek(); } public int peek(){ int data = top.data; top = top.next; return data; } public boolean empty() { return top == null; } }
Examples of stack applications
Number system conversion
For the conversion of decimal numbers to R-based numbers, we generally use the decimal number and the decimal number to take the remainder. The highest digit often appears last, which just fits the last-in-first-out stack. For example, 1024 to octal:
The highest bit appears last, but the stack happens to be last in first out. Example of base conversion:
/**
* 进制转换
* @param input
* @param decimal
*/
private static void binaryConversion(int input, int decimal) {
if(decimal == 0){
return;
}
Stack<Integer> stack = new Stack<>();
while (input != 0){
stack.push(input % decimal);
input = input / decimal;
}
String result = "";
while (!stack.empty()){
result = result + stack.pop();
}
System.out.println(result);
}
Reference
- "A New Perspective on Data Structure and Algorithm Analysis" Zhou Xingni, Ren Zhiyuan, Ma Yanzhuo edited by China Industry and Information Technology Publishing Group
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。