Source: Internet
Author: User

09. cyclic queue and chain queue, 09 cyclic queue**I. queue and cyclic queue****1. Queue**(1) A queue is a linear table that only allows insertion at one end and deletion at the other end. A queue is a linear table of Fiirst In First Out (FIFO. The end that can be inserted is called the team end, and the end that can be deleted is called the team header. According to the definition of the queue, the queuing operation is to append an element at the end of the queue without moving any element. Therefore, the time complexity is O (1 ). The queue deletion operation is different from the stack. The queue element is listed in the queue header, that is, the position with a small value of 0. to delete an element, all elements of the queue need to be moved, so the event complexity is O (n ). (2) front/rear pointer: to avoid the trouble of handling when there is only one element, the overlap between the team end and the team header makes the processing troublesome. All two pointers are introduced, and the front pointer points to the team Header element, the rear Pointer Points to the next position of the element at the end of the team, so that when the front is equal to the rear, the queue is empty (empty Queue), rather than the remaining element in the queue.**2. Abstract Data Types of queues**The ADT queue Data is a linear table. The element has the same type, and the adjacent element has a precursor and a Successor Relationship. Operation InitQueue (* Q): during initialization, an empty queue Q. DestoryQueue (* Q) is created. If queue Q exists, it is destroyed. ClearQueue (* Q): Clear the queue Q by GetHead (Q, * e): If the queue Q exists and is not empty, use e to return the queue Header element of the queue Q. EnQueue (* Q, e): If the queue Q exists and is not empty, insert the new element e to the queue Q, which is called the team end element. DeQueue (* Q, * e): deletes the queue Q squadron Header element and returns its value QueueLength (Q) with e: returns the number of queue Q elements endADT**3. cyclic queue****(1) Definition**: The sequential storage structure that connects the beginning and end of a queue is called a cyclic queue, which is used to solve the "false overflow" problem.**(2) full team conditions**: Generally, when front = rear, the queue may be empty or full. Therefore, we assume that the queue is empty when front = rear; when the queue is full, the array has a free space. Because rear may be larger or smaller than front. In this definition, when the queue meets the condition "(rear + 1) % QueueSize = front", we think the queue is full (QueueSize is the maximum storage capacity of the queue ).**(3) queue length formula**When rear> front, the queue length is rear-front. When rear <front, the queue length is (QueueSize-front) + (0 + rear ), font, rear, and QueueSize are all array subscripts. Calculated queue formula: (rear-front + QueueSize) % QueueSize**(4) sequential storage structure of cyclic queues**Typedef int QElemTypetypedef struct {QElemType data [MAXSIZE]; int front; // team head pointer int rear; // team end pointer. If the queue is not empty, it points to the next position of the team end element} SqQueue; (5) cyclic queue related operations. initialize a cyclic queue QStatus InitQueue (SqQueue * Q) {Q-> front = 0; Q-> rear = 0; return OK;} B. calculate the length of the cyclic queue/* The number of elements returned by Q, that is, the current length of the queue */int QueueLength (SqQueue Q) {return (Q. rear-Q.front + MAXSIZE) % MAXSIZE;} C. loop queue insertion: if the queue is not full, the inserted element e is the new team end element Status EnQueue (SqQueue * Q, QElemType e) {if (Q-> rear + 1) % M AXSIZE = Q-> front) // determines whether the stack is full (rear + 1) % QueueSize = front) return ERROR; q-> data [Q-> rear] = e; Q-> rear = (Q-> rear + 1) % MAXSIZE; // The rear pointer moves one digit to the back, return OK to the array header;} D. cyclic queue deletion operation: If the queue is not empty, the Q squadron Header element is deleted. Use e to return its value Status EnQueue (SqQueue * Q, QElemType * e) {if (Q-> rear = Q-> front) return ERROR; // The queue is empty. condition: rear = front * e = Q-> data [Q-> front]; // assign the team Header element to e Q-> front = (Q-> front + 1) % MAXSIZE; // The front pointer moves to the back position. If it is at the end, return OK to the array header;} conclusion: the order is stored. If it is not a cyclic queue, the time performance of the algorithm is not high, but the cyclic queue faces the problem that arrays may overflow. Therefore, we will introduce the chained storage structure of the queue in the next section.**Ii. Queue chain Storage Structure****1. Chain queue**: The chain storage structure of the queue is actually a single-chain table of a linear table, but it can only end with the header, also known as the chain queue. For ease of operation, the head Pointer Points to the head node of the chain queue, and the end Pointer Points to the terminal node. The queue is empty when both the front pointer and the rear pointer are directed to the front point.**2. Chain queue Structure**Typedef int QElemType/* node Structure */typedef struct QNode {QElemType data; // data field struct QNode * next; // pointer field} QNode, * Queueptr; /* queue linked list structure */typedef struct {Queueptr front, rear; // team head, Team tail pointer} LinkQueue; 3. the queuing operation algorithm of the chain queue: essentially, the end of the chain table is inserted to the node, and the end Pointer Points to the new node. create a space for the new node s and determine whether the storage is allocated successfully. B. store the inserted element in the data field of the new node s and initialize the pointer field of s. assign the new node s with element eto the successor of the original queue node; d. set the current s as the end node, and rear points to s

Implementation: Insert a new team end element whose Element e is Q

Status EnQueue (LinkQueue * Q, QElemType e) {QueuePtr s = (QueuePtr) malloc (sizeof (QNode); // create a space for the new node s if (! S) // storage allocation failure exit (OVERFLOW); s-> data = e; // store Element e to the data domain s of the new node s-> next = NULL; // initialize the pointer field Q-> rear-> next = s of the new node; // assign the value of s of the new node with element eto the successor Q-> rear = s of the original queue node; // set the current s as the end node, and rear points to s}

Implementation: If the queue is not empty, delete the queue Header element of Q, use e to return its value, and Return OK; otherwise, an ERROR is returned.

Status EnQueue (LinkQueue * Q, QElemType e) {QueuePtr p; if (Q-> front = Q-> rear) return ERROR; // The queue is empty. p = Q-> front-> next; // The successor node of the header node to which the header pointer is directed (the node to be deleted) save it to p * e = p-> data; // assign the data field data of the node to be deleted to e Q-> front-> next = p-> next; // assign the p-> next value to the p-> next of the first node of the team if (Q-> rear = p) // if the first node is the end of the team, after deletion, point the rear to the header node Q-rear = Q-> front; free (p); return OK ;}Iii. Performance Analysis of cyclic and link queues 1. the basic operation time complexity of cyclic queue and chain queue is O (1); 2. the cyclic queue applies for a good space in advance and does not release it during use. The chain queue does not need to apply for space in advance, but there will be some event overhead each time the node is applied for and released; 3. the cyclic queue must have a fixed length, which may result in space waste. The chain queue requires a pointer field, which may produce some space overhead, therefore, we recommend that you use cyclic queues when you can determine the maximum queue length.

Related Article