This section discusses two interesting data structures: Stack and queue.
What is Stack, the so-called Stack is a linear table with Operations Limited at the end of the table. Because the end of a table needs to be inserted or deleted, it has a special meaning. The end of the table is called the Top of the stack, and the other end is fixed, it is called a Bottom ). When there is no data element in the Stack, it is called an Empty Stack ). This is similar to a rice box for food delivery. The upper layer contains braised pork, boiled fish in the middle layer, and chicken legs in the lower layer. You need to extract these dishes, which leads to the First in last out feature of the stack ). Details: Add.
Stack is usually recorded as: S = (a1, a2 ,..., An). S is the 1st Letter of the English word stack. A1 is the bottom element of the stack, and an is the top element of the stack. The n data elements follow a1, a2 ,..., An goes into the stack sequentially, while the order of the outbound stack is the opposite. an is the first outbound stack and a1 is the last outbound stack. Therefore, stack operations follow the principle of Last In First Out (LIFO) or First In Last Out (FILO). Therefore, stack is also called a LIFO table or a FILO table. Stack operations.
The formal definition of Stack is as follows: Stack (Stack) is short as S, is a binary group, and Gu is defined as S = (D, R)
Where: D is a finite set of data elements;
R is a finite set of relationships between data elements.
Overview of some basic stack operations: As the stack can only be operated at the top of the stack, the stack cannot insert or delete any element in the stack. Therefore, stack operations are a subset of linear table operations. Stack operations include inserting and deleting elements at the top of the stack, taking the elements at the top of the stack, and determining whether the stack is empty.
Similarly, we use a C # generic interface to represent the stack, and the method members in the interface represent basic operations. For convenience and conciseness, the generic stack interface is named IStack (in fact, there is no generic interface IStack in C # <T>, generic stacks are inherited from interfaces such as IEnumerable <T> and ICollection, which are essentially different from linear tables ).
The source code of the stack interface definition is as follows.
Public interface IStack <T> {
// Initial condition: Stack exists; Operation Result: return the number of data elements in the stack.
Int GetLength (); // obtain the stack length. pseudo-code index ++
// Initial condition: the stack exists. Operation Result: true is returned if the stack is empty. Otherwise, false is returned. Pseudo code if (top = null) return true; else return false;
Bool IsEmpty (); // determines whether the stack is empty.
// Initial condition: Stack exists; Operation Result: Empty stack. Pseudocode top = null;
Void Clear (); // Clear operation
// Initial condition: the stack exists. Operation Result: the new data element with the item value is added to the top of the stack, and the stack changes. Pseudocode top = item; index ++;
Void Push (T item); // stack inbound operation
// Initial condition: the stack exists and is not empty. Operation Result: The top element of the stack is removed from the stack. The stack has changed. pseudocode: return top; index --;
T Pop (); // stack-out operation
// Initial condition: the stack table exists and is not empty. Operation Result: the value of the top element of the stack is returned, and the stack does not change. Pseudo-code get top;
T GetTop (); // gets the top element of the stack.
}
Stack is also divided into two forms: sequential stack and chain stack.
Sequence Stack ):
A continuous storage space is used to store data elements in the Stack. Such a Stack is called a Sequence Stack ). Similar to a sequence table, a one-dimensional array is used to store data elements in the sequence stack. The top indicator of the stack is located at the end where the subscript of the array is 0. The top indicator changes with insertion and deletion. When the stack is empty, top =-1. Is the relationship between the top of the stack indicator of the sequential stack and the data elements in the stack.
The source code implementation of the sequential Stack class SeqStack <T> is as follows.
Public class SeqStack <T>: IStack <T> {
Private int maxsize; // The maximum storage space of the sequential Stack
Private T [] data; // array, used to store the data elements in the sequential Stack
Private int top; // indicates the top pointer of the stack of the sequential stack.
// Indexer
Public T this [int index]
{
Get
{
Return data [index];
}
Set
{
Data [index] = value;
}
}
// Capacity attribute
Public int Maxsize
{
Get
{
Return maxsize;
}
Set
{
Maxsize = value;
}
}
// Stack top attributes
Public int Top
{
Get
{
Return top;
}
}
// The constructor performs initialization to assign values.
Public SeqStack (int size)
{
Data = new T [size];
Maxsize = size;
Top =-1;
}
// Calculate the stack length by adding a header pointer
Public int GetLength ()
{
Return top + 1;
}
:
// Judge whether the sequence stack is empty
// Determines whether the header pointer is-1. If it is null, it is false if it is not.
Public bool IsEmpty ()
{
If (top =-1)
{
Return true;
}
Else
{
Return false;
}
}
As shown in:
// Judge whether the sequential stack is full or the maximum size is equal. Return true or false if the returned result is not equal.
Public bool IsFull ()
{
If (top = maxsize-1)
{
Return true;
}
Else
{
Return false;
}
}
Everything is in the legend.
// Place it on the top of the stack
Public void Push (T item)
{
// If it is full, do not add
If (IsFull ())
{
Console. WriteLine ("Stack is full ");
Return;
}
// Add to the top
Data [++ top] = item;
}
Everything is in the legend
// Exit the stack and subtract the pointer from the back of the stack
Public T Pop ()
{
T tmp = default (T );
If (IsEmpty ())
{
Console. WriteLine ("Stack is empty ");
Return tmp;
}
Tmp = data [top];
-- Top;
Return tmp;
Everything is in the legend.
// Obtain the data element at the top of the stack and direct it to the element to be displayed.
Public T GetTop ()
{
// If it is null, a default value is returned.
If (IsEmpty ())
{
Console. WriteLine ("Stack is empty! ");
Return default (T );
}
Return data [top];
The details are as follows:
}
}
}
This is an introduction to the sequence stack.
Next, we will go to another stack-Introduction to the chain stack.
What is a chain Stack, the so-called chain Stack is another storage method of the Stack is chain storage, such a Stack is called a chain Stack (Linked Stack ). A chain stack is usually represented by a single-chain table, which simplifies a single-chain table. Therefore, the structure of the link stack node is the same as that of the single-link table node ,. Because the operation of the stack is only performed at one end, the stack is set to the head of the linked list for convenience, and no header node is required.
The source code implementation of the Node (Node <T>) is as follows:
Public class Node <T>
{
Private T data; // data domain
Private Node <T> next; // reference the domain
// Constructor
Public Node (T val, Node <T> p)
{
Data = val;
Next = p;
}
// Constructor
Public Node (Node <T> p)
{
Next = p;
}
// Constructor
Public Node (T val)
{
Data = val;
Next = null;
}
// Constructor
Public Node ()
{
Data = default (T );
Next = null;
}
// Data domain attributes
Public T Data
{
Get
{
Return data;
}
Set
{
Data = value;
}
}
// Reference domain attributes
Public Node <T> Next
{
Get
{
Return next;
}
Set
{
Next = value;
}
}
}
Is the chain stack.
Think of a chain stack as a generic class named LinkStack <T>. In the LinkStack <T> class, the top field indicates the top indicator of the stack. Because the stack can only access the data elements at the top of the stack, the stack top indicator of the stack cannot indicate the number of data elements at the stack. Therefore, when determining the length of a chain stack, the data elements in the stack must be pushed out one by one. Each time a data element is pushed out of the stack, the counter is increased by one, but this will damage the stack structure. To retain the data elements in the stack, You need to first press the data elements in the stack into another stack, calculate the length, and then press the data elements into the original stack. However, this algorithm has a high space complexity and time complexity. Therefore, the above two algorithms are not an ideal solution. The ideal solution is to add a field num in the LinkStack <T> class to indicate the number of nodes in the chain stack.
The implementation of link stack <T> is described as follows.
Public class LinkStack <T>: IStack <T> {
Private Node <T> top; // stack top indicator
Private int num; // number of nodes in the stack
// Stack top indicator attributes
Public Node <T> Top
{
Get
{
Return top;
}
Set
{
Top = value;
}
}
// The number of elements attribute is counted.
Public int Num
{
Get
{
Return num;
}
Set
{
Num = value;
}
}
// The constructor initializes the function.
Public LinkStack ()
{
Top = null;
Num = 0;
}
// Calculate the length of the chain stack and return the computing complexity. The complexity of this algorithm is O (1)
Public int GetLength ()
{
Return num;
}
// Clears the chain stack. The complexity of this algorithm is O (1)
Public void Clear ()
{
Top = null;
Num = 0;
}
// Judge whether the chain stack is null to determine whether the counting variable and the header pointer are null. Return true. Otherwise, false. The complexity of this algorithm is O (n)
Public bool IsEmpty ()
{
If (top = null) & (num = 0 ))
{
Return true;
}
Else
{
Return false;
}
}
// Stack inbound operations
Public void Push (T item)
{
Node <T> q = new Node <T> (item );
If (top = null)
{
Top = q;
}
Else
{
Q. Next = top;
Top = q;
}
++ Num;
}
// The operation header pointer of the outbound stack is subtracted. The complexity of this algorithm is 1.
Public T Pop ()
{
If (IsEmpty ())
{
Console. WriteLine ("Stack is empty! ");
Return default (T );
}
Node <T> p = top;
Top = top. Next;
-- Num;
Return p. Data;
}
// Obtain the value of the top node of the stack and return the value of the header pointer. The complexity of this algorithm is one.
Public T GetTop ()
{
If (IsEmpty ())
{
Console. WriteLine ("Stack is empty! ");
Return default (T );
}
Return top. Data;
}
}
This is the introduction of the chain stack. It also introduces the obvious application of a stack, which is the application of a simple universal calculator.
We all know that two basic stacks, operand stack, and operator stack, must be used to complete computing when operators are first grammar used, however, using these two stacks alone has some limitations. Therefore, I introduced the third stack (op stack) during the design. Let's take a look at it.
When two stacks are used, what will happen if the expression 2-3 */6 # is used?
Step # Number stack operator stack description of the remaining strings currently entered 1 blank #2-3 */6 #2 blank #2-3 */6 #32 #-3 */6 #42 #-3 */6 #52 3 #-*/6 #62 3 #-*/6 # *> /, calculation 2*3,-</, push (/) 76 #-/6 #86 6 #-/#/> #, calculation 6/6,-> #, trying to calculate, an error is reported due to the lack of a number character. The error is located at minus 9 and is empty #-
In this case, the error message is: there may be errors near minus. However, the problem actually exists in the vicinity of * Or/. The positioning result of this error is not satisfactory.
So let's see what will happen if the third stack is introduced as the symbol stack? The symbol stack function stores all the symbols in the analysis process, including the number operators and operators.
Step # Number stack operator stack symbol stack description of the remaining strings currently input 1 null #2-3 */6 #2 null #2-3 */6 #32 #2- 3 */6 #42 #-#2-3 */6 #52 3 #-#2-3 */6 #62 3 #-* #2-3 */6 # *> /, 2*3,-</, push (/) 76 #-/#2 6/6 #86 6 #-/#2 6/6 #/> #. After 6 is thrown, perform absolute neighbor check on/and 6 in the stack first, and then perform absolute neighbor check on 6 and 2, but it is found that 6 and 2 cannot be adjacent, so an error is reported. The error is located at the division number.
The error is located at/. The error message is: there is an error near divide. In this way, the user is more likely to find the problem in the expression. Each operation (corresponding to SemanticAnalyzer. fakeCalculate () method), uses the absolute adjacent priority table to check the adjacent symbols in the symbol stack pop-up. If the two symbols at the top of the stack cannot be adjacent, an error is reported immediately. Details ,:
What is a Queue? The so-called Queue is a linear table where the insert operation is limited to the end of the table while other operations are limited to the header of the table. The end of the table for insertion is called a Rear, and the header for other operations is called a Front ). When no data element exists in a pair column, it is called an Empty pair column (Empty Queue ). The queue is usually counted as Q = (a1, a2 ,..., An) Q is the 1st Letter of the English word queue. A1 indicates the head element and an indicates the end element. The n elements are based on a1, a2 ,..., An is in the same order as an is in the same order. a1 is the first and an is the last one. Therefore, column operations are performed according to the principle of First In First Out or Last In Last Out. This is like waiting for a ticket. Therefore, a queue is also called a FIFO table or a LILO table. Queue Q operations. Details ,:
The formal definition of a Queue is as follows: the Queue (Queue) is short as Q, which is a binary group. Q = (D, R) Where: D is a finite set of data elements; is a finite set of relationships between data elements. In real life, there are many examples similar to queue. For example, to get money in the queue, first take the money first, and then rank it at the end of the team.
Similarly, we use a C # generic interface to represent a queue, and the method members in the interface represent basic operations. For convenience and conciseness, the generic queue interface is named IQueue <T> (in fact, in C #, the generic queue class is inherited from the IEnumerable <T>, ICollection, and IEnumerable interfaces without the IQueue <T> generic interface ). The source code of the queue interface IQueue <T> is defined as follows.
Public interface IQueue <T> {
Int GetLength (); // evaluate the length of the queue. initial condition: the queue exists. Operation Result: return the number of data elements in the queue. Everything starts ,:
Bool IsEmpty (); // determines whether the column is empty; initial condition: the queue exists; Operation Result: true is returned if the queue is empty; otherwise, false is returned. All situations ,:
Void Clear (); // Clear the queue. initial condition: the queue exists. Operation Result: Empty the queue.
Void In (T item); // The initial condition for entering the queue: the queue exists. Operation Result: add the new data element with the value of item to the end of the queue, and the queue changes.
T Out (); // the details of the header node returned for the team-Out operation
The complexity of this algorithm is O (1)
T GetFront (); // obtain the Header element of the first element.
The complexity of this algorithm is O (1)
The complexity of this algorithm is O (1)
}
This is the basic introduction of queue.
Next I will introduce the queue application. I am playing wuziqi, using and saving the chess spectrum, and regretting the operations. This makes good use of the advanced features of the queue for storage. When you regret it, you will pull the position of the pawns out.
This is the introduction of queues and stacks.