Stack and queue are two special linear tables. Their logical structure is the same as that of linear tables, but their calculation rules are more restrictive than linear tables. Therefore, they are also called linear tables with limited operation. Stack and queue are widely used in various programming. |
Queue (Head and end can be moved)
1. Definition A queue is a linear table that only allows insertion at one end and deletion at the other end. (1)Front)Allowed to delete (2)Team end (rear)End-to-End insertion allowed (3) When no element exists in the queue, it is calledEmpty Queue (there are two empty Queues: 1 before inserting any elements. 2. After all elements are displayed). (4) A queue is also called a linear table of first in first out.FIFO table. The queue is modified according to the first-in-first-out principle. New members always join at the end of the team, and members who leave each time are always on the queue. [Example] add A1, A2,… to the queue in sequence ,..., After an, A1 is the first element and an is the last element. The order of exiting the queue can only be A1, A2 ,..., An.
2. Basic logical operations of queues (1) initqueue (q) is left empty. Construct an empty queue Q. (2) queueempty (q) if the queue Q is empty, the true value is returned; otherwise, the false value is returned.
(3) If the queue Q is full, the true value is returned; otherwise, the false value is returned. Note: This operation only applies to the ordered storage structure of the queue.
(4) enqueue (Q, X) If the queue Q is not full, the element x is inserted to the end of the Q. This operation is shortJoin.
(5) dequeue (q) If the queue Q is not empty, delete the queue Header element of Q and return this element. This operation is shortTeam-out.
(6) queuefront (q) If the queue Q is not empty, the first element of the queue is returned, but the status of the queue Q is not changed. |
Ordered queue
1. ordered queue
(1) definitions of ordered queues
The ordered storage structure of queues is called ordered queues. Ordered queues are actually sequential tables with limited operations.
(2) Representation of ordered queues
① Like the sequence table, the sequence queue uses a vector space to store elements in the current queue.
② Because the head and tail positions of the queue are changed, set two pointers, front and rear, respectively, to indicate the positions of the head and tail elements in the vector space, their initial values should be set to 0 during queue initialization.
(3) basic operations of the ordered queue (the operating element of the time-out period is in the Operation pointer)
① When entering the queue: Insert the new element into the position indicated by rear, and add rear to 1.
② When leaving the team: Delete the elements referred to by front, add front 1, and return the deleted elements.
Note:
① When the head and tail pointers are equal, the queue is empty. (So there are two empty Queues: 1. No elements have been inserted before
2. All elements are displayed)
② In a non-empty queue, the head pointer always points to the head element, and the end pointer always points to the next position of the end element.
(4) overflow in the ordered queue
① "Underflow" Phenomenon
When the queue is empty, the overflow caused by queue operations. "Underflow" is a normal phenomenon and is often used as a condition for controlling the transfer of programs.
② "Truly overflow"
When the queue is full, stack-based operations will cause Space overflow. "True overflow" is an error. Try to avoid it.
③ "False overflow"
As the number of head and tail pointers increases and does not decrease during the operations, the space of the deleted elements will never be reused. When the actual number of elements in the queue is much smaller than the vector space size, the tail pointer may not be allowed to join the queue because it has exceeded the upper bound of the vector space. This phenomenon is called "false overflow.
[Example] assume that the following Operation Sequence acts on an empty sequence queue:
Enqueue, dequeue, enqueue, dequeue ,...
Although the number of queue elements cannot exceed 1 at any time, as long as the sequence is long enough, the vector space defined in advance will generate a pointer out-of-bounds error no matter how large it is.
2. cyclic queue
To make full use of Vector Space and overcome the "false overflow" phenomenon, you can think of the vector space as a ring that starts and ends at the beginning and ends, and call it a circular vector. A queue is called a circular queue ).
(1) Basic operations of cyclic queue
When a cyclic queue is used for queuing and queuing operations, the header and tail pointer must be added with 1 to move forward. However, when the head and tail Pointer Points to the upper bound of the vector (QueueSize-1), the result of adding 1 operation is pointing to the lower bound 0 of the vector. In this loop, the plus 1 operation can be described as follows:
① Method 1:
If (I + 1 = queuesize) // I indicates front or rear
I = 0;
Else
I ++;
② Method 2 -- using "modulo operation"
I = (I + 1) % queuesize;
(2) Processing of cyclic queue Boundary Conditions
In a cyclic queue, the tail pointer catches up with the head pointer while the tail pointer is in the queue. When the head pointer catches up with the tail pointer when the queue is out, the head and tail pointers are equal when the queue is full. Therefore, the condition front = rear cannot be used to determine whether the queue is "empty" or "full ". [See animation demonstration]
There are at least three solutions to this problem:
(1) set a Boolean variable to distinguish the empty and full values of the queue;
② Use less space of one element. Before the appointment, test whether adding 1 to the end pointer in a loop is equal to the head pointer. If the result is equal, the end pointer is considered to be full (note: the Unit indicated by rear is always empty );
③ Use a counter to record the total number of elements in the queue (that is, the queue length ).
(3) define the type of cyclic queue
# Define queur size 100 // this value should be defined according to the actual situation
Typedef char queue datatype; // The type of datatype depends on the specific application
Typedef sturet {// header pointer, which points to the Header element when the team is not empty
Int front; // tail pointer. When the team is not empty, it points to the next position of the team's tail element.
Int rear; // counter, which records the total number of elements in the team
Datatype data [queuesize]
} Cirqueue;
(4) basic operation of cyclic queue
In the third method, there are six basic operations of the cyclic queue:
① Leave the team empty
Void initqueue (cirqueue * q)
{
Q-> front = Q-> rear = 0;
Q-> COUNT = 0; // set the counter to 0.
}
② Empty team judgment
Int queueempty (cirqueue * q)
{
Return Q-> COUNT = 0; // no element in the queue is empty.
}
③ Judge that the team is full
Int queuefull (cirqueue * q)
{
Return Q-> COUNT = queuesize; // when the number of elements in the team is equal to the queuesize, the team is full.
}
④ Join
Void enqueue (cirqueuq * q, datatype X)
{
If (queuefull (q ))
Error ("queue overflow"); // The team is full
Q-> count ++; // The number of queue elements plus 1
Q-> data [q-> rear] = x; // Insert a new element to the end of the team
Q-> rear = (Q-> rear + 1) % queuesize; // Add the end pointer to 1 in a loop
⑤ Team-out
Datatype dequeue (cirqueue * q)
{
Datatype temp;
If (queueempty (q ))
Error ("queue underflow"); // team Overflow
Temp = Q-> data [q-> front];
Q-> count --; // The number of queue elements minus 1
Q-> front = (Q-> front + 1) & queuesize; // Add 1 to the header pointer in a loop.
Return temp;
}
6. element of the leader
Datatype queuefront (cirqueue * q)
{
If (queueempty (q ))
Error ("queue If empty .");
Return Q-> data [q-> front];
}
Chain queue
1. Definition of chain queue The chain storage structure of a queue is referred to as a chain queue. It is a single-chain table that is only deleted from the header and inserted at the end of the table.
2. structure type description of blockchain queue Note: Add a tail pointer pointing to the last node on the linked list to facilitate insertion at the end of the table. For details about the chain queue, Q is a linkqueue pointer. 3. Basic operation of blockchain queue (1) Empty team Void initqueue (linkqueue * q) { Q-> front = Q-> rear = NULL; } (2) Empty team Determination Intqueueempty (linkqueue * q) { Return Q-> front = NULL & Q-> rear = NULL; // In fact, you only need to judge whether the head pointer of the team is null. } (3) join Void enqueue (linkqueue * q, datatype X) {// Insert element X to the end of the chain queue Queuenode * P = (queuenode *) malloc (sizeof (queuenode); // apply for a new node P-> DATA = x; P-> next = NULL; If (queueempty (q )) Q-> front = Q-> rear = P; // insert X into an empty queue Else {// X Insert the end of a non-empty queue Q-> rear-> next = P; // * after P is linked to the original team's End Node Q-> rear = P; // the team's tail Pointer Points to the new tail. } } (4) team-out Datatype dequeue (linkqueue * q) { Datatype X; Queuenode * P; If (queueempty (q )) Error ("queue underflow"); // Underflow P = Q-> front; // point to the peer node X = p-> data; // Save the data of the origin node. Q-> front = p-> next; // remove the first node from the chain If (Q-> rear = P) // only one node exists in the original queue. The queue becomes empty after deletion, and the header pointer of the queue is empty. Q-> rear = NULL; Free (p); // release the deleted head node Return X; // return the original header data. } (5) retrieve the element from the queue Header Datatype queuefront (linkqueue * q) { If (queueempty (q )) Error ("queue If empty ."); Return Q-> front-> data; } Note: ① Similar to the chain stack, there is no need to consider the full team calculation and overflow. ② In the dispatch algorithm, you generally only need to modify the header pointer. However, when there is only one node in the old team, this node is both the head and end of the team. Therefore, you must modify the end pointer when deleting this node and the queue becomes empty after deleting this node. ③ The above describes the basic operations of the queue without a head node chain. Similar to a single-chain table, you can add a header node before the header node to simplify the processing of the boundary condition. |
Bytes -------------------------------------------------------------------------------------------------------------------------
Stack definition and basic operations
1. Stack Definition
Stack is a linear table that only inserts and deletes operations at one end of the table.
(1) This end is usually called insert or deleteStack top(Top), the other end is calledStack bottom(Bottom ).
(2) When there is no element in the table, it is calledEmpty Stack.
(3) the stack is a linear table of last in first out (referred toLIFO table.
Stack modification is based on the principle of "back-to-first-out. Each deletion (Stack rollback) Is always the "latest" element in the current stack, that is, the last insert (Stack entryIs inserted at the bottom of the stack.
[Example] the element is A1, A2 ,..., The order of an to stack is an, An-1 ,..., A1.
2. Basic stack operations
(1) initstack (s)
Construct an empty stack S.
(2) stackempty (s)
Empty stack determination. If S is empty, true is returned; otherwise, false is returned.
(3) stackfull (s)
Judge that the stack is full. If S is full, true is returned; otherwise, false is returned.
Note:
This operation is only applicable to the stack's sequential storage structure.
(4) Push (S, X)
Stack. If Stack S is not satisfied, element x is inserted to the top of stack S.
(5) Pop (s)
Stack rollback. If Stack S is not empty, delete the top element of stack S and return this element.
(6) stacktop (s)
Take the top element of the stack. If Stack S is not empty, the top element of the stack is returned, but the stack status is not changed.
Sequential Stack
The stack sequence storage structure is called sequence stack. It is a sequence table with limited operations.
1. Sequence stack Type Definition
# Define stacksize 100 // assume that the pre-allocated stack space can contain a maximum of 100 elements.
Typedef char datatype; // assume that the data type of the stack element is a character.
Typedef struct {
Datatype data [stacksize];
Int top;
} Seqstack;
Note:
① Storing elements in the sequence stack with vectors
② The bottom position of the stack is fixed and can be set to any endpoint at both ends of the Vector
③ The top position of the stack changes with the stack Entry and Exit operations. An integer top (usually called top as the top pointer of the stack) is used to indicate the top position of the current stack.
2. Basic operations of the sequential Stack
Prerequisites:
Set S to a pointer variable of the seqstack type. If the bottom position of the stack is at the low end of the vector, that is, S-> data [0] is the bottom element of the stack.
(1) stack operations
Add S-> top to 1
Note:
① S-> Top = StackSize-1 indicates the stack is full
②"Overflow"Symptom: When the stack is full, the stack overflow occurs when the stack is full.
Overflow is an error. Try to avoid it.
(2) stack rollback
During stack rollback, the S-> Top minus 1 is required.
Note:
① S-> top <0 indicates empty Stack
②"UnderflowSymptom: overflow caused by rollback when the stack is empty.
Underflow is a normal phenomenon and is often used as a condition for program control transfer.
Detailed changes of the sequence stack during stack loading and stack rollback operations [see animation demonstration]
3. basic operations of sequential Stack
(1) Empty Stack
Void initstack (seqstack * s)
{// Leave the sequential stack empty
S-> Top =-1;
}
(2) Empty stack Determination
Int stackempty (seqstack * s)
{
Return S-> Top =-1;
}
(3) judge that the stack is full
Int stackfull (seqstack * ss)
{
Return S-> Top = StackSize-1;
}
(4) Stack
Void push (S, X)
{
If (stackfull (s ))
Error ("stack overflow"); // overflow, exit
S-> data [++ S-> top] = x; // Add the top pointer of the stack to 1 and add X to the stack
}
(5) rollback
Datatype POP (s)
{
If (stackempty (s ))
Error ("Stack underflow"); // off, exit
Return S-> data [S-> top --]; // after the top element of the stack is returned, the top pointer of the stack is reduced by 1.
}
(6) taking the top element of the stack
Datatype stacktop (s)
{
If (stackempty (s ))
Error ("Stack is empty ");
Return S-> data [S-> top];
}
4. Two stacks share the same bucket
When two stacks are used in a program at the same time, the stacks of the two stacks can be located at both ends of the vector space, so that the two stacks can expand to the middle. When a stack contains more elements than half of the vector space, as long as there are not many elements in the other stack, the former can occupy part of the latter's storage space.
Overflow occurs only when the whole vector space is full of two stacks (that is, the two stacks meet each other. Therefore, the two stacks share a vector space with a length of M and the two stacks occupy a comparison of vector spaces with two lengths of M/2 and M/2 respectively, the probability of overflow in the former is much lower than that in the latter.
Chain Stack
The chain storage structure of a stack is called a chain stack.
1. Chain stack Type Definition
A chain stack is a single-chain table with no additional header nodes. The top pointer of the stack is the head pointer of the linked list.
The stack types are described as follows:
Typedef struct stacknode {
Datatype data
Struct stacknode * Next
} Stacknode;
Typedef struct {
Stacknode * Top; // stack top pointer
} Linkstack;
Note:
① The linkstack structure type is defined to facilitate the modification of the top pointer itself in the function body.
② To record the number of elements in the stack, you can define the number attribute in the linkstack type.
2. Basic operations of the chain Stack
(1) Empty Stack
Void initstack (linkstack * s)
{
S-> Top = NULL;
}
(2) Empty stack Determination
Int stackempty (linkstack * s)
{
Return S-> Top = NULL;
}
(3) Stack
Void push (linkstack * s, datatype X)
{// Insert element x into the chain stack Header
Stacknode * P = (stacknode *) malloc (sizeof (stacknode ));
P-> DATA = X;
P-> next = s-> top; // Insert the new node * P to the head of the stack.
S-> Top = P;
}
(4) stack rollback
Datatype POP (linkstack * s)
{
Datatype X;
Stacknode * P = s-> top; // Save the top pointer of the stack
If (stackempty (s ))
Error ("Stack underflow."); // Underflow
X = p-> data; // Save the top node data of the stack.
S-> Top = p-> next; // removes the top node of the stack from the chain.
Free (P );
Return X;
}
(5) Get the top element of the stack
Datatype stacktop (linkstack * s)
{
If (stackempty (s ))
Error ("Stack is empty .")
Return S-> top-> data;
}
Note:
Nodes in the chain Stack are dynamically allocated. Therefore, overflow is not considered and stackfull operations are not required.
Stack and queue are widely used. Stack and queue can be used as their data structure as long as the problem meets the following principles: first-in-first-out and first-in-first-out.
Stack applications
1. Digital Conversion
It is easy to solve the problem of converting a non-negative decimal integer n to another equivalent B-base number through the "Division B remainder method.
[Example] convert the decimal number 13 to the binary number.
Answer: divide the remainder by two and the remainder is 1, 0, 1, and 1 in sequence. Then, the decimal number is converted to 1101.
Analysis: because the first obtained remainder is the lowest Bit Of the conversion result, and the last obtained remainder is the highest bit of the conversion result, it is easy to use the stack to solve the problem.
The conversion algorithm is as follows:
Typedef int datatype; // The datatype definition of the sequence stack should be changed to an integer type.
Void multibaseoutput (int n, int B)
{// Assume that N is a non-negative decimal integer and returns the equivalent hexadecimal number of B.
Int I;
Seqstack S;
Initstack (& S );
While (n) {// generate B-digit numbers from right to left and import them to the stack
Push (& S, N % B); // Add Bi to stack 0 <= I <= J
N = N/B;
}
While (! Stackempty (& S) {// return the output when the stack is not empty
I = POP (& S );
Printf ("% d", I );
}
}
In addition to numeric conversion, stack can also be used to solve problems such as bracket matching check, row editing, and expression solving.
2. Stack and Recursion
(1) Recursion
The so-calledRecursionIt refers to a function, process, or data structure that directly or indirectly applies the definition itself. It is called recursion or recursion.
Recursion is a powerful mathematical tool that can simplify and clarify the description and solution of a problem.
Recursive Algorithms are often easier to design than non-recursive algorithms, especially when the problem itself or the involved data structure is defined recursively.
(2) design steps of Recursive Algorithms
Step 1 (recursive step ):The large original problem is divided into one or more smaller subproblems with features similar to the original problem. That is, a large problem is recursively described using a small subproblem. The methods for solving the original problem can also be used to solve these subproblems.
Step 2:Determine one or more minimum subproblems that can be solved directly without decomposition (calledRecursive termination conditions).
[Example] The factorial of a non-negative integer N can be recursively defined:
(3) The role of stack in the internal implementation of recursive algorithms.
① When calling a function: the system constructs an activity record consisting of a parameter table and a return address for the caller and pushes it to the top of the stack provided by the system at the runtime, then, the control of the program is transferred to the called function. If the called function has local variables, allocate space to the top of the stack at the runtime. Therefore, activity records and these local variables form an activity structure that can be used by the called function.
Note:
The content of the parameter table is an actual parameter, and the return address is the location of the next instruction of the function call statement.
② When the executed function is completed: the system will return the activity structure at the top of the stack at the runtime to the stack, the control of the program is transferred to the caller for further execution based on the return address saved in the stack rollback activity structure.
Queue application-partner issues
1. Problem Description
Let us assume that at the weekend dance, men and ladies are lined up when they enter the ballroom. At the beginning of the dance, a partner is assigned to each of the men's and women's teams. If the initial number of members of the two teams is different, the unpaired members of the long team will wait for the next dance. We need to write an algorithm to simulate the above-mentioned partner pairing problem.
2. Problem Analysis
Men or women who join the team are also assigned partners. Therefore, this problem has a typical first-in-first-out feature. The queue can be used as the data structure of the algorithm.
In the algorithm, assume that the records of men and women are stored in an array as input, then scan the elements of the array in sequence, and decide whether to enter the men's or women's teams based on gender. After the construction of the two queues is complete, the two teams are sequentially assigned with partners with the current line elements until a queue becomes empty. At this time, if a team is still waiting for the matching person, the algorithm outputs the number of waiting persons in the queue and the name of the waiting person in the queue) it will be the first person to get a partner at the beginning of the next dance.
3. Specific algorithms and related types
Typedef struct {
Char name [20];
Char sex; // gender. 'F' indicates female, and 'M' indicates male.
} Person;
Typedef person datatype; // change the data type of the element in the queue to person.
Void dancepartner (person dancer [], int num)
{// Structural array dancer stores dancing men and women. Num is the number of dancing people.
Int I;
Person P;
Cirqueue mdancers, fdancers;
Initqueue (& mdancers); // men's queue Initialization
Initqueue (& fdancers); // initialization of Ms queue
For (I = 0; I <num; I ++) {// enter the dance dancer according to their gender.
P = dancer [I];
If (P. Sex = 'F ')
Enqueue (& fdancers. p); // enter female
Else
Enqueue (& mdancers. p); // enter the men's team
}
Printf ("The Dancing partners are:/n ");
While (! Queueempty (& fdancers )&&! Queueempty (& mdancers )){
// Enter the name of the partner in sequence
P = dequeue (& fdancers); // ladies
Printf ("% s", p. Name); // print the name of the lady
P = dequeue (& mdancers); // men's team
Printf ("% s/n", p. Name); // print men's names
}
If (! Queueempty (& fdancers) {// output the remaining number of ladies and the name of the head lady
Printf ("/n there are % d women waitin for the next round./N", fdancers. Count );
P = queuefront (& fdancers); // gets the team Header
Printf ("% s will be the first to get a partner./N", p. Name );
} Else
If (! Queueempty (& mdancers) {// output the remaining number of men and the name of the Team Leader
Printf ("/n there are % d men waiting for the next round./N", mdacers. Count );
P = queuefront (& mdancers );
Printf ("% s will be the first to get a partner./N", p. Name );
}
} // Dancerpartners