definition
We learned the data structure of stack earlier. We know that it is characterized by data in first and data out later. In contrast to the stack, queues are characterized by data first in first out. That is, first in firstr out, referred to as FIFO.
The queue only allows data insertion at one end of the table and data deletion at the other end. This is consistent with the queuing in life. The first to enter the queue is the first to leave. In the linked list, the end where data can be inserted is called the rear, and the end where data can be deleted is called the front. Suppose that the data a,b,c,d,e,f are input into a queue, then the input order is a,b,c,d,e,f. The order of output is also a,b,c,d,e,f.
basic operation
- Initialize a queue
Status InitQueue(LinkQueue *q)
- Destroy a queue
Status DestoryQueue(LinkQueue *q)
- Empty a queue
Status ClearQueue(LinkQueue *q)
- Determine whether the queue is empty
Status QueueEmpty(LinkQueue *q)
- Returns the number of elements available in the queue, that is, the length of the queue
int QueueLength(LinkQueue *q)
- Return to the head of the team
Status GetHead(LinkQueue Q, QElemType* e)
- Add element from end of queue
tatus EnQueue(LinkQueue* Q, QElemType e)
- Delete queue header element
Status DeQueue(LinkQueue* Q, QElemType* e)
- Queue traversal
Status QueueTraverse(LinkQueue Q, void (Visit)(QElemType))
Code implementation of basic operation methods
- Initialize a queue
Status InitQueue(LinkQueue* Q) { if(Q == NULL) { return ERROR; } (*Q).front = (*Q).rear = (QueuePtr) malloc(sizeof(QNode)); if(!(*Q).front) { exit(OVERFLOW); } (*Q).front->next = NULL; return OK; }
- Destroy a queue
Status DestroyQueue(LinkQueue* Q) { if(Q == NULL) { return ERROR; } while((*Q).front) { (*Q).rear = (*Q).front->next; free((*Q).front); (*Q).front = (*Q).rear; } return OK; }
- Empty a queue
Status ClearQueue(LinkQueue* Q) { if(Q == NULL) { return ERROR; } (*Q).rear = (*Q).front->next; while((*Q).rear) { (*Q).front->next = (*Q).rear->next; free((*Q).rear); (*Q).rear = (*Q).front->next; } (*Q).rear = (*Q).front; return OK; }
- Determine whether the queue is empty
Status QueueEmpty(LinkQueue Q) { if(Q.front == Q.rear) { return TRUE; } else { return FALSE; } }
- Returns the number of elements available in the queue, that is, the length of the queue
int QueueLength(LinkQueue Q) { int count = 0; QueuePtr p = Q.front; while(p != Q.rear) { count++; p = p->next; } return count; }
- Return to the head of the team
Status GetHead(LinkQueue Q, QElemType* e) { QueuePtr p; if(Q.front == NULL || Q.front == Q.rear) { return ERROR; } p = Q.front->next; *e = p->data; return OK; }
- Add element from end of queue
Status EnQueue(LinkQueue* Q, QElemType e) { QueuePtr p; if(Q == NULL || (*Q).front == NULL) { return ERROR; } p = (QueuePtr) malloc(sizeof(QNode)); if(!p) { exit(OVERFLOW); } p->data = e; p->next = NULL; (*Q).rear->next = p; (*Q).rear = p; return OK; }
Picture presentation
- Delete queue header element
Status DeQueue(LinkQueue* Q, QElemType* e) { QueuePtr p; if(Q == NULL || (*Q).front == NULL || (*Q).front == (*Q).rear) { return ERROR; } p = (*Q).front->next; *e = p->data; (*Q).front->next = p->next; if((*Q).rear == p) { (*Q).rear = (*Q).front; } free(p); return OK; }
Picture presentation
- Queue traversal
Status QueueTraverse(LinkQueue Q, void (Visit)(QElemType)) { QueuePtr p; if(Q.front == NULL) { return ERROR; } p = Q.front->next; while(p != NULL) { Visit(p->data); p = p->next; } printf("\n"); return OK; }
The source code implements the chain queue, so a header node that does not contain data is set. In fact, the queue operation can be carried out without setting this node, but adding a header node makes the process of deleting the traversal lamp more convenient and easy to understand
All code files
- Status code macro definition header file
Status.h
#ifndef STATUS_H #define STATUS_H #include <stdio.h> /* Status code */ #Define true 1 / / true / true #Define false 0 / / false / no #Define OK 1 / / pass / succeed #Define error 0 / / error / failure //This status code has been defined in the system. To prevent conflicts #ifndef OVERFLOW #Define overflow - 2 / / stack overflow #endif //This status code has been defined in the system. To prevent conflicts #ifndef NULL #define NULL ((void*)0) #endif /* Status code type */ typedef int Status; /* Boolean type */ typedef int Boolean; #endif
- Function definition header file
LinkQueue.h
#include <stdio.h> #include <stdlib.h> #include "Status.h" /* Chain element type definition */ typedef int QElemType; // Queue element structure typedef struct QNode { QElemType data; struct QNode* next; } QNode, * QueuePtr; // Queue structure typedef struct { QueuePtr front; // Queue head pointer QueuePtr rear; // Tail pointer } LinkQueue; // Chained storage representation of queues /* * initialization * Construct an empty chain team. * If the initialization is successful, it returns OK; otherwise, it returns ERROR. */ Status InitQueue(LinkQueue* Q); /* * Destroy (structure) * Free up memory occupied by chain queue. */ Status DestroyQueue(LinkQueue* Q); /* * Empty (content) * Here, we need to release the space at the non head node in the chain queue. */ Status ClearQueue(LinkQueue* Q); /* * Air judgment * Judge whether the chain team contains valid data * Return value: * TRUE : The chain queue is empty * FALSE: Chain queue is not empty */ Status QueueEmpty(LinkQueue Q); /* * count * Returns the number of valid elements contained in the chain queue. */ int QueueLength(LinkQueue Q); /* * Value * Get the queue header element and store it in e. * If it can be found, return OK; otherwise, return ERROR. */ Status GetHead(LinkQueue Q, QElemType* e); /* * Join the team * Add the element e to the end of the queue. */ Status EnQueue(LinkQueue* Q, QElemType e); /* * Out of the team * Remove the element of the queue header and store it in e. */ Status DeQueue(LinkQueue* Q, QElemType* e); /* * ergodic * Access queue Q with visit function */ Status QueueTraverse(LinkQueue Q, void(Visit)(QElemType)); #endif
- Function implementation header file
LinkQueue.c
#include"LinkQuquq.h" #include"Status.h" Status InitQueue(LinkQueue* q) { if (q == NULL) { return ERROR; } (*q).front = (*q).rear = (QueuePtr)malloc(sizeof(QNode)); if (!(*q).front) { exit(OVERFLOW); } (*q).front->next = NULL; return OK; } //The queue destruction function is not often used Status DestoryQueue(LinkQueue* q) { if (q == NULL) { return ERROR; } while ((*q).front) { (*q).rear = (*q).front->next; free((*q).front); (*q).front = (*q).rear; } return OK; } //The content is empty, but the space of the middle non head node should be released Status ClearQueue(LinkQueue* q) { if (q = NULL) { return ERROR; } (*q).rear = (*q).front->next; while ((*q).rear) { (*q).front->next = (*q).rear->next; free((*q).rear); (*q).rear = (*q).front->next; } (*q).rear = (*q).front; return OK; } //Determine whether the queue is empty Status QueueEmpty(LinkQueue* q) { if (q->front == q->rear) { return TRUE; } else { return FALSE; } } //Returns the number of valid elements in the queue int QueueLength(LinkQueue* q) { int count = 0; QueuePtr p = q->front; while (p != q->rear) { count++; p = p->next; } return count; } //Take out the team head element Status GetHead(LinkQueue* q,int* e) { QueuePtr p; if (q->front == NULL || q->front == q->rear) { return ERROR; } p = q->front->next; *e = p->data; return OK; } Status Enter(LinkQueue* q, int e) { QueuePtr p; if (q == NULL || (*q).front == NULL) { return ERROR; } p = (QueuePtr)malloc(sizeof(QNode)); if (!p) { exit(OVERFLOW); } p->data = e; p->next = NULL; (*q).rear->next = p; (*q).rear = p; return OK; } //Get out of the queue and remove the element of the queue head Status Out(LinkQueue* q, int e) { QueuePtr p; if (q == NULL || q->front==NULL || q->front == q->rear) { return ERROR; } p = (*q).front->next; e = p->data; (*q).front->next = p->next; if ((*q).rear == p) { (*q).front = (*q).rear; } free(p); return OK; } void QueueTraverse(LinkQueue* q) { QueuePtr p; if (q->front == NULL) { return ERROR; } p = q->front->next; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); }
- Test main function
LinkQueue-main.c
#include <stdio.h> #Include "linkqueue. H" / * * 03 stack and queue**// // Test functions, printing integers void PrintElem(QElemType e); int main(int argc, char** argv) { LinkQueue Q; int i; QElemType e; printf(" function InitQueue \n"); { printf(" Initialize chain team Q ...\n"); InitQueue(&Q); } printf(" function QueueEmpty \n"); { QueueEmpty(Q) ? printf(" Q Empty!!\n") : printf(" Q Not empty!\n"); } printf(" function EnQueue \n"); { for(i = 1; i <= 6; i++) { EnQueue(&Q, 2 * i); printf(" element \"%2d\" Join the team...\n", 2 * i); } } printf(" function QueueTraverse \n"); { printf(" Q The elements in are: Q = "); QueueTraverse(Q, PrintElem); } printf(" function QueueLength \n"); { i = QueueLength(Q); printf(" Q The length of the is %d \n", i); } printf(" function DeQueue \n"); { DeQueue(&Q, &e); printf(" Team head element \"%d\" Out of the team...\n", e); printf(" Q The elements in are: Q = "); QueueTraverse(Q, PrintElem); } printf(" function GetHead \n"); { GetHead(Q, &e); printf(" The value of the queue header element is \"%d\" \n", e); } printf(" function ClearQueue \n"); { printf(" empty Q front:"); QueueEmpty(Q) ? printf(" Q Empty!!\n") : printf(" Q Not empty!\n"); ClearQueue(&Q); printf(" empty Q After:"); QueueEmpty(Q) ? printf(" Q Empty!!\n") : printf(" Q Not empty!\n"); } printf(" function DestroyQueue \n"); { printf(" Destroy Q front:"); Q.front != NULL && Q.rear != NULL ? printf(" Q Exist!\n") : printf(" Q non-existent!!\n"); DestroyQueue(&Q); printf(" Destroy Q After:"); Q.front != NULL && Q.rear != NULL ? printf(" Q Exist!\n") : printf(" Q non-existent!!\n"); } return 0; } // Test functions, printing integers void PrintElem(QElemType e) { printf("%d ", e); }