Queue (can be compared with the stack to learn)
Idea: The queue implements a FIFO (FIRST-IN,FIRST-OUT,FIFO) strategy. (Introduction to Algorithms)
Definition: A queue is a linear table (with a linear/predecessor relationship) that allows only one end of an insert operation and a delete operation at the other end. ("Big liar data Structure")
Terms:
Both ends of the queue: team Header (head): One end of the delete operation. End of Team (tail): one end of the insertion operation.
Action: Insert operation for queue (insert): enqueue (enqueue). Delete operation for queue (delete): out of Line (dequeue).
Empty queue : A queue that does not contain any data elements (empty queue). (This corresponds to the term full queue, which emphasizes the status of the data in the queue)
Queue underflow (underflow): An Out-of-band operation on an empty queue. Queue overflow (overflow): Enqueue a full queue.
II. abstract data type for queues (ADT)
The Main method implementation/operation of the queue (mainly refer to "Big talk Data Structure"):
1. Initialize the queue (initqueue)
2. Empty queue (Clearqueue) (clears the queue's data and frees memory if memory is dynamically allocated )
3. Determine if the queue is an empty queue (Queueempty)
4. Get team head element (GetHead)
5. Queue (EnQueue)
6. The team (DeQueue)
7. Number of elements to get the queue (queuelength)
Data structure implementation of the queue: (Queue belongs to a data structure of linear table)
1. Sequential queue : Sequential table implementation, using sequential storage structure. (data is stored in successive storage units according to the predecessor relationship, array implementation)
2. chain queue : Linked list implementation, the use of chain storage structure. (data is connected by pointer or index and is not continuously stored in the storage unit, linked-list implementation)
Three, the thinking of the queue
1. Sequential tables are implemented using circular queues (sequential storage structures with tail-to-toe) to conserve queue storage space and avoid large movements of queue data elements. (Implementation: Introduction of two pointers to team head and tail of the team when using arrays)
2. Expansion: Double-ended Queue (deque): Its insert and delete operations can be done at both ends. STL Implementation Deque (#include <deque>) in C + + (from the introduction to algorithms)
3. Expansion: Priority queue. (from "Programming Zhu Ji Nanxiong")
4. Printer processing is a simple application of a queue.
Iv. algorithm C Implementation (c + + can use the STL in the queue: #include <queue>)
The sequential table implementation of this queue adopts static array, and the linked list implements dynamic memory;
Loop queue : Sequential table implementation (sequential storage structure):
1. Sequential table implementation adopts circular queue instead of simple sequential queue, avoids the whole data element moving before and after, and improves the algorithm time performance.
2.head indicates the index value of the team header data in the array, tail indicates the index value of the tail data in the array plus 1 (note loop), when the team is full: (Team tail tail + 1)% Queue Length size = Team head head; Empty team: tail tail = Team head head; queue data element length: ( Team tail tail-team head head + Queue Length size)% Queue Length size
Header file Queue.h:
/** * @file queue.h * @brief queue data structure header. * The queue use sequence list. * @author Chenxilinsidney * @version 1.0 * @date 2015-01-21 * * #ifndef __queue_h__#define __queue_h__#include <STDIO.H&G t; #include <stdlib.h> #include <string.h>//#define Ndebug#include <assert.h>///function return State#ifndef ok#define OK 1#endif#ifndef error#define ERROR 0#endif#ifndef true#define TRUE 1#endif#ifndef False#define FALSE 0#endif///data type, can be modifiedtypedef int Status; < status data Typetypedef int elementtype; < element data Typetypedef int commontype; < common data type///queue array Maz length, can be modified#define queue_maxsize 1000///queue data structure typedef struct {ElementType data[queue_maxsize]; < queue elements Commontype head; < queue head Data index Commontype tail; < queue tail Data index}queue;///queue methodsInitialize queuevoid initqueue (queue* Q);//Clear queuevoid Clearqueue (queue* Q);///Detect if Queue is Emptystatus q Ueueempty (queue* Q);///Get Queue lengthcommontype queuelength (queue* Q);///Get head element from the Queuestatus GetHead (queue* Q, elementtype* e);///Insert element to the Queuestatus EnQueue (queue* Q, ElementType e);///delete element from The Queuestatus DeQueue (queue* Q, elementtype* e); #endif//__queue_h__
Implement file Queue.c:
/** * @file queue.c * @brief Queue method implements. * The methods use <assert.h> to help debugging the program. * The queue use sequence list. * @author Chenxilinsidney * @version 1.0 * @date 2015-01-21 * * #include "queue.h"/** * @brief initialize the queue. * * @param [in,out] Q queue struct pointer * */void initqueue (queue* q) {assert (Q! = NULL); Initialize index only, ignore the queue data Q->head = 0; Q->tail = 0;} /** * @brief Clear the queue. * * @param [in,out] Q queue struct pointer * */void clearqueue (queue* q) {assert (Q! = NULL && q->head &G t;= 0 && q->tail >= 0); Set index only, ignore the queue data Q->head = 0; Q->tail = 0;} /** * @brief detect if the queue is empty. * * @param [in] Q queue struct pointer * * @return return TRUE if empty, else return falqe */status queueempty (Que ue* q) {assert (Q! = NULL && q->head >= 0 && q->tail >= 0); Detect Index VAlue if (q->head = = Q->tail) return TRUE; else return FALSE;} /** * @brief Get queue Length. * * @param [in] Q queue struct pointer * * @return Queue Length */commontype queuelength (queue* q) {assert (Q! = NULL && q->head >= 0 && q->tail >= 0); Return (Q->tail-q->head + queue_maxsize)% Queue_maxsize;} /** * @brief get head element from the queue. * * @param [in] Q queue struct pointer * @param [out] e the element * * @return return OK if success, else return ERROR */status gethead (queue* q, elementtype* e) {assert (q! = NULL && E! = null && q->head &G t;= 0 && q->tail >= 0); if (Q->head = = Q->tail) return ERROR; Get element from queue *e = q->data[q->head]; return OK;} /** * @brief Insert element to the queue. * * @param [in,out] Q queue struct pointer * @param [in] e the element to be insert * @return return OK if sUccess, else return ERROR */status EnQueue (queue* q, ElementType e) {assert (Q! = NULL && q->head >= 0 &am p;& q->tail >= 0); Queue is full if ((Q->tail + 1)% Queue_maxsize = = Q->head) return ERROR; Set data first and then increase tail index q->data[q->tail] = e; Q->tail = (q->tail + 1)% Queue_maxsize; return OK;} /** * @brief Delete element from the queue. * * @param [in,out] Q queue struct pointer * @param [out] e the element to be deleted * * @return return OK and Set E if success, else return ERROR */status DeQueue (queue* q, elementtype* e) {assert (q! = NULL && E! = null && q->head >= 0 && q->tail >= 0); Queue is empty if (Q->tail = = Q->head) return ERROR; Get data first and then increase head index *e = q->data[q->head]; Q->head = (q->head + 1)% Queue_maxsize; return OK;}
chain queue : Linked list implementation (chained storage structure):
1. The head of the single-linked list heads is the head node, which itself does not hold data, the internal next points to the node that holds the head element of the team, the trailing pointer of the single-linked list tail The tail element of the queue, and the internal next points to null;
2. Use the auxiliary variable count to record the length of the data element, avoid traversing the linked list to get the length information (the data bits of the head node are not used because the data type may not be sufficient to hold the length)
Header file Queue.h:
/** * @file queue.h * @brief queue data structure header. * The queue use linked list. * @author Chenxilinsidney * @version 1.0 * @date 2015-01-21 * * #ifndef __queue_h__#define __queue_h__#include <STDIO.H&G t; #include <stdlib.h> #include <string.h>//#define Ndebug#include <assert.h>///function return State#ifndef ok#define OK 1#endif#ifndef error#define ERROR 0#endif#ifndef true#define TRUE 1#endif#ifndef False#define FALSE 0#endif///data type, can be modifiedtypedef int Status; < status data Typetypedef int elementtype; < element data Typetypedef int commontype; < common data type///queue data structuretypedef struct Queuenode {ElementType data; < queue elements struct queuenode* next; < queue node Pointer}queuenode, *queueptr;typedef struct queue {queueptr head; < queue head data pointer queueptr tail; <Quaue tail data pointer commontype count; < Quaue data count}queue;///Queue methods///initialize queuevoid initqueue (queue* Q);//Clear Queuevoid Clearqueu E (queue* Q);///Detect if queue is Emptystatus queueempty (queue* Q);///Get Queue lengthcommontype queuelength (queue* q); Get head element from the Queuestatus gethead (queue* q, elementtype* e);///Insert element to the Queuestatus EnQueue (Q ueue* Q, ElementType e);///delete element from the Queuestatus DeQueue (queue* Q, elementtype* e); #endif//__queue_h__
Implement file Queue.c:
/** * @file queue.c * @brief Queue method implements. * The methods use <assert.h> to help debugging the program. * The queue use linked list. * @author Chenxilinsidney * @version 1.0 * @date 2015-01-21 * * #include "queue.h"/** * @brief initialize the queue. * * @param [in,out] Q queue struct pointer * */void initqueue (queue* q) {assert (Q! = NULL); if (Q->head = (queueptr) malloc (sizeof (queuenode)) = = = NULL) {assert (0); Exit (Exit_failure); } Q->tail = q->head; Q->head->next = NULL; Q->count = 0;} /** * @brief Clear the queue. * * @param [in,out] Q queue struct pointer * */void clearqueue (queue* q) {assert (Q! = NULL && Q->count & gt;= 0); Set index only, ignore the queue data queueptr New_node = q->head; while (New_node! = q->tail) {Q->head = new_node->next; Free (New_node); New_node = q->head; } q->count = 0;} /** * @brief detect if the queue is empty. * * @pAram[in] Q Queue struct pointer * * @return return TRUE if empty, else return falqe */status queueempty (queue* Q) {assert (Q! = NULL && q->count >= 0); Detect index value if (Q->head = = Q->tail) return TRUE; else return FALSE;} /** * @brief Get queue Length. * * @param [in] Q queue struct pointer * * @return Queue Length */commontype queuelength (queue* q) {assert (Q! = NULL && q->count >= 0); return q->count;} /** * @brief get head element from the queue. * * @param [in] Q queue struct pointer * @param [out] e the element * * @return return OK if success, else return ERROR */status gethead (queue* q, elementtype* e) {assert (q! = NULL && E! = null && Q->count & gt;= 0); if (Q->head = = Q->tail) return ERROR; Get element from queue *e = q->head->next->data; return OK;} /** * @brief Insert element to the queue. * * @param [in,out] Q Queue struct pointer * @param [in] e the element to is insert * * @return return OK If success, else return ER ROR */status EnQueue (queue* q, ElementType e) {assert (Q! = NULL && q->count >= 0); Queueptr New_node; if (New_node = (queueptr) malloc (sizeof (queuenode)) = = = NULL) {assert (0); Exit (Exit_failure); } new_node->data = e; New_node->next = NULL; Q->tail->next = New_node; Q->tail = New_node; q->count++; return OK;} /** * @brief Delete element from the queue. * * @param [in,out] Q queue struct pointer * @param [out] e the element to be deleted * * @return return OK and Set E if success, else return ERROR */status DeQueue (queue* q, elementtype* e) {assert (q! = NULL && E! = null && q->count >= 0); Queue is empty if (Q->tail = = Q->head) return ERROR; Queueptr Old_node = q->head->next; *e = old_node->data; Q->head->next= old_node->next; if (Q->tail = = old_node) Q->tail = q->head; Free (Old_node); q->count--; return OK;}
Loop Queue and Chain queue comparison:
The loop queue is applicable to the maximum number of data elements can be controlled situation;
The chain queue is suitable for the case that the maximum number of data elements is not controllable, so the memory overhead is increased by storing pointers outside;
The time complexity of the queue and the team is O (1).
V. Practice- using two queues to implement a stack
Think: We can use one of the empty queue as a buffer, the stack when the non-empty queue, queued elements are the elements of the stack; When the stack takes a non-empty queue, all other elements outside the last element are merged into the team into the empty queue, and the last element is then out of the team as an element of the stack. In this scenario, there is always an empty queue in the two queue as the buffer, each stack will be a set of all elements of the team out and queued operations (the last element only for the team operation), the time complexity of the Stack is O (1) (The detection of whether the queue is an empty queue is not done by traversing the queue, but by a count variable or secondary variable, or by other secondary flags to determine which is the empty queue), and the time complexity of the stack is O (n).
Other scenarios: The above scheme does not fix which queue (A or B) is a buffer, as long as the empty queue. This scheme uses 1 queues (such as queue a) to hold elements, while another queue (such as queue B) remains empty when there is no action, and when the stack operation, the elements that are removed from the tail are queued to queue B by queue A, and then the elements are enqueued back to queue a by queue B. This scheme is less efficient than the one above, because it has an operation that queues all the elements in B from queue B to queue A when it is in the stack, which can actually be avoided.
When implemented, be aware that:
1. Two each queue is a null-time stack error handling, the stack can be arbitrarily used one (can also specify the use of empty queue 1), non-empty queue when the stack error handling. (The main thinking direction is that the queue is an empty queue and a full queue of the two special States)
2. Each method of the call stack implements the queue method instead of directly processing variables in the queue's data structure (assuming that the data in the queue is closed, only the method can be called).
Algorithm C Implementation:
Header file Stack_by_queue.h (except that the data structure used by the queue is different from the normal queue, the method implements the same function interface):
/** * @file Stack_by_stack.h * @brief implement of a stack by and queues. * @author Chenxilinsidney * @version 1.0 * @date 2015-01-22 * * #ifndef __stack_by_queue_h__#define __stack_by_queue_h__#in Clude "queue.h"///Stack data structure by the queuetypedef struct stack { queue Q1; Queue Q2;} stack;///stack methods///initialize stackvoid initstack (stack* s);///Clear Stackvoid Clearstack (stack* s);///Detect if Stack is Emptystatus stackempty (stack* s);///Get Stack lengthcommontype stacklength (stack* S);///get top element from T He stackstatus GetTop (stack* s, elementtype* e);///push element to the Stackstatus push (stack* S, ElementType e);///Pop Element from the Stackstatus Pop (stack* S, elementtype* e); #endif //__stack_by_queue_h__
implement file Stack_by_queue.c:
/** * @file stack_by_queue.c * @brief Stack method implements. * The methods use <assert.h> to help debugging the program. * The stack use the queues. * @author Chenxilinsidney * @version 1.0 * @date 2015-01-21 * * #include "stack_by_queue.h"/** * @brief initialize the stack . * * @param [in,out] S stack struct pointer * */void initstack (stack* s) {assert (S! = NULL); Initqueue (&S->Q1); Initqueue (&S->Q2);} /** * @brief clear the stack. * * @param [in,out] S stack struct pointer * */void clearstack (stack* s) {assert (S! = NULL); Clearqueue (&S->Q1); Clearqueue (&S->Q2);} /** * @brief detect if the stack is empty. * * @param [in] S stack struct pointer * * @return return TRUE if empty, else return FALSE */status stackempty (Sta ck* s) {assert (s! = NULL); if (Queueempty (&s->q1) && queueempty (&S->Q2)) return TRUE; else return FALSE;} /** * @brief get stack length. * * @param [in] S STACK struct pointer * * @return stack length */commontype stacklength (stack* s) {assert (S! = NULL); Return Queuelength (&S->Q1) + queuelength (&S->Q2);} /** * @brief get top element from the stack. * * @param [in] S stack struct pointer * @param [out] e the element * * @return return OK if success, else return ERROR */status GetTop (stack* s, elementtype* e) {assert (s! = null && E! = null); if (Queueempty (&s->q1) = = FALSE) {while (DeQueue (&S->Q1, E)) {EnQueue (&S->Q2, *e) ; } return OK; } else if (Queueempty (&s->q2) = = FALSE) {while (DeQueue (&S->Q2, E)) {EnQueue (&S-> Q1, *e); } return OK; } else {return ERROR; }}/** * @brief push element to the stack. * * @param [in,out] S stack struct pointer * @param [in] e the element to be insert * * @return return OK if S Uccess, else return ERROR */status Push (stack* S, ELementtype e) {assert (S! = NULL); if (Queueempty (&s->q1) = = FALSE) {return EnQueue (&S->Q1, E); } else {return EnQueue (&S->Q2, E); }}/** * @brief pop element from the stack. * * @param [in,out] S stack struct pointer * @param [out] e the element to be deleted * * @return return OK and Set E if success, else return ERROR */status Pop (stack* s, elementtype* e) {assert (s! = null && E! = null); if (Queueempty (&s->q1) = = FALSE) {Commontype Keep_one = queuelength (&s->q1)-1; while (keep_one--) {DeQueue (&s->q1, E); EnQueue (&S->Q2, *e); } DeQueue (&S->Q1, E); return OK; } else if (Queueempty (&s->q2) = = FALSE) {Commontype Keep_one = queuelength (&S->Q2)-1; while (keep_one--) {DeQueue (&S->Q2, E); EnQueue (&S->Q1, *e); } DeQueue (&S->Q2, E); return OK; } else {return ERROR; }}
Vi. Priority queues
(To learn "programming Zhu Ji Nanxiong" supplement)
Vi. Summary
about the queue of the knowledge point and the stack itself is not much, mainly to understand the queue of advanced first-out thinking, can be combined with the actual problem of the application and law implementation.
Special topic in data structure--queue