Cyclic queue
Queues are generally divided into two categories: one is dynamic chained Queue (the core idea is linked list, but some functions of linked list are missing) and the other is static (sequential) queue (its core is array implementation. To be precise, it is implemented by vector space. vector space is like a piece of memory opened up and directed to its address by our pointer ). The ordered queue is actually an ordered table with limited operations. Because the positions of the queue head and end are changed, generally, two pointers, front and rear, are set to indicate the positions of the header and tail elements in the vector space. Their initial values should be set to 0 during queue initialization. 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 of "fake overflow" often results in a waste of memory resources, and a loop Queue (beginning and end) is generated ). To overcome the "false overflow" Phenomenon in cyclic queue, you can think of the vector space as a ring connecting the beginning and end, and store the cyclic queue in it. 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 ". There are two solutions to this problem: one is to 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 ),; the second is to use a counter to record the total number of elements in the queue (that is, the queue length ). We usually use the first method, that is, to use less space of an element.
Operations related to cyclic queue
1. Initialization: Create an array. Set the length of the array to n = 5 (it is required that the array is full when there are n-1 elements). The initialization team header team end value is 0;
2. Join
First, determine whether the queue is full: (team end + 1) % array length = whether the team header is set up? That is, the end of the team is closely aligned with the head of the team;
Assign values to the next element at the end of the team;
ADD team tails to 1;
3. Team out
First determine whether the queue is empty: if the first and end of the queue are equal, the queue must be empty (but the first and end of the queue are not set to 0, this is determined by the subscript position of the array after initialization, team-up, and team-out operations)
Save a value for leaving the team;
Add 1 to the team's head;
Instance description
? <SPAN style = "FONT-SIZE: 14px"> # include <stdio. h> # include <malloc. h> # include <stdlib. h> typedef struct Queue {int * pBase; // pBase points to the array name (usually the static Queue uses the cyclic Queue) int front; // array subscript, int rear;} QUEUE; // QUEUE indicates struct Queue void init (QUEUE *); // initialize bool en_queue (QUEUE *, int ); // enter the bool full_queue (QUEUE *); // determine whether the cyclic QUEUE is full bool del_queue (QUEUE *, int *); // leave the bool empty_queue (QUEUE *); // determine whether the cyclic queue is empty bool traverse_queu E (QUEUE *); // traverses the output int length (QUEUE *); // calculates the length of the cyclic QUEUE int main () {queue q; int val; init (& Q); en_queue (& Q, 1); en_queue (& Q, 2); en_queue (& Q, 3); en_queue (& Q, 4 ); traverse_queue (& Q); if (del_queue (& Q, & val) printf ("the team is successful, and the team element value is % d \ n", val ); else printf ("failed! "); Traverse_queue (& Q); printf (" Queue length: % d \ n ", length (& Q); return 0 ;} void init (QUEUE * pQ) {pQ-> pBase = (int *) malloc (sizeof (int) * 5); // create an array, set the length of the array to n = 5 (it is required that the array is full when there are n-1 elements ), during initialization, the front and rear values of the Queue members are all 0 if (NULL = pQ-> pBase) {printf ("dynamic memory allocation failed! \ N "); exit (-1);} pQ-> front = 0; pQ-> rear = 0;} bool full_queue (QUEUE * pQ) {if (pQ-> rear + 1) % 5 = pQ-> front) return true; else return false;} bool en_queue (QUEUE * pQ, int val) {if (full_queue (pQ) {printf ("the queue is full. Failed to join! \ N "); return false;} pQ-> pBase [pQ-> rear] = val; pQ-> rear = (pQ-> rear + 1) % 5; // Add 1 return true at the end of the team;} bool del_queue (QUEUE * pQ, int * pVal) {if (empty_queue (pQ) return false; * pVal = pQ-> pBase [pQ-> front]; pQ-> front = (pQ-> front + 1) % 5; return true ;} bool empty_queue (QUEUE * pQ) {if (pQ-> rear = pQ-> front) // when the QUEUE is not empty, the rear and front are definitely not equal and return true; else return false;} bool traverse_queue (QUEUE * pQ) {int I = pQ-> front; if (Empty_queue (pQ) {printf ("the queue is empty. traversal failed! \ N "); return false;} printf (" queue elements: "); while (I! = PQ-> rear) {printf ("% d", pQ-> pBase [I]); I = (I + 1) % 5 ;} printf ("\ n"); return true;} int length (QUEUE * pQ) {int len = 0; int I = pQ-> front ;; if (empty_queue (pQ) return 0; // The queue is empty and the length is 0 while (I! = PQ-> rear) {I = (I + 1) % 5; ++ len;} return len ;}</SPAN >#include <stdio. h> # include <malloc. h> # include <stdlib. h> typedef struct Queue {int * pBase; // pBase points to the array name (usually the static Queue uses the cyclic Queue) int front; // array subscript, int rear;} QUEUE; // QUEUE indicates struct Queuevoid init (QUEUE *); // initialize bool en_queue (QUEUE *, int ); // enter the bool full_queue (QUEUE *); // determine whether the cyclic QUEUE is full bool del_queue (QUEUE *, int *); // leave the bool empty_queue (QUEUE *); // determine whether the cyclic queue is empty bool Traverse_queue (QUEUE *); // traverses the output int length (QUEUE *); // calculates the length of the cyclic QUEUE, int main () {queue q; int val; init (& Q); en_queue (& Q, 1); en_queue (& Q, 2); en_queue (& Q, 3); en_queue (& Q, 4 ); traverse_queue (& Q); if (del_queue (& Q, & val) printf ("the team is successful, and the team element value is % d \ n", val ); else printf ("failed! "); Traverse_queue (& Q); printf (" Queue length: % d \ n ", length (& Q); return 0 ;} void init (QUEUE * pQ) {pQ-> pBase = (int *) malloc (sizeof (int) * 5); // create an array, set the length of the array to n = 5 (it is required that the array is full when there are n-1 elements ), during initialization, the front and rear values of the Queue members are all 0 if (NULL = pQ-> pBase) {printf ("dynamic memory allocation failed! \ N "); exit (-1);} pQ-> front = 0; pQ-> rear = 0;} bool full_queue (QUEUE * pQ) {if (pQ-> rear + 1) % 5 = pQ-> front) return true; else return false;} bool en_queue (QUEUE * pQ, int val) {if (full_queue (pQ) {printf ("the queue is full. Failed to join! \ N "); return false;} pQ-> pBase [pQ-> rear] = val; pQ-> rear = (pQ-> rear + 1) % 5; // Add 1 return true at the end of the team;} bool del_queue (QUEUE * pQ, int * pVal) {if (empty_queue (pQ) return false; * pVal = pQ-> pBase [pQ-> front]; pQ-> front = (pQ-> front + 1) % 5; return true ;} bool empty_queue (QUEUE * pQ) {if (pQ-> rear = pQ-> front) // when the QUEUE is not empty, the rear and front are definitely not equal and return true; else return false;} bool traverse_queue (QUEUE * pQ) {int I = pQ-> front; if (empty_qu Eue (pQ) {printf ("the queue is empty. traversal failed! \ N "); return false;} printf (" queue elements: "); while (I! = PQ-> rear) {printf ("% d", pQ-> pBase [I]); I = (I + 1) % 5 ;} printf ("\ n"); return true;} int length (QUEUE * pQ) {int len = 0; int I = pQ-> front ;; if (empty_queue (pQ) return 0; // The queue is empty and the length is 0 while (I! = PQ-> rear) {I = (I + 1) % 5; ++ len;} return len ;}
Note:
1. the pointer can only be moved when the player is in or out of the queue. In other cases, the pointer cannot be moved.
2. Queue initialization: the value of front and rear is zero;
3. queue is not empty: front represents the first element of the queue, and rear represents the next element of the last valid element of the queue.
4. The most intuitive difference between the sequential queue and the cyclic queue is that the first and end of the cyclic queue are connected to form a ring, but the sequential queue is not a ring (which usually leads to a waste of memory resources ).
5. queue is widely used, and all time-related operations can be used in queues.