Queue (sequential queue, cyclic queue, chain queue) super detailed explanation

Posted by GYK on Sun, 31 Oct 2021 19:56:00 +0100

Basic knowledge of queue

Queue (ADT): a linear table that is limited to inserting at one end of the table and deleting at the other end of the table. Among them, the rear is the position where the new elements enter the queue in turn, and the front is the position where the elements in the queue leave the queue in turn. In vernacular, it means that a group of people queue up to buy rice. The people in front of them leave after buying rice. This is going out of the queue. The people in the back join the queue to buy rice. This is joining the queue. The first is the head of the team, and the last is the tail.

Queues are First In First Out (FIFO) linear data structures. This is the same situation as buying rice. The first comer buys rice first. In contrast to queue FIFO, the stack is LIFO.

1, Sequential queue

The order of the queue is represented by a one-dimensional array. Its data structure is defined as follows:

typedef struct//Define a queue
{
	int data[MaxSize];//Define an array
	int front, rear;//Defines the queue head pointer and the queue tail pointer
}SqQueue;

It should be noted that front points to the subscript position of the previous unit of the queue head element, and rear points to the subscript position of the queue tail element. MaxSize indicates the maximum number of elements allowed to be stored in the queue.

At the beginning, F and r will set the position pointing to - 1. At the beginning, the sequence of empty queues is shown in (a) below (for demonstration convenience, f represents front and r represents rear). When elements join the team, first add 1 to the subscript at the end of the team, and then elements join the team; When the element is out of the team, first add 1 to the subscript of the team head, and then the element is out of the team. The situation after elements a, B and C join the team in turn is shown in figure (b) below. Every time an element joins the team, r will be + 1. Because there are three elements in figure (b) below, r+3=4. The situation after two element dequeueing operations is shown in figure (c) below. Every time you dequeue, f is + 1. Because two elements are dequeued in figure (c) below, f+2=1; The following figure (d) shows the situation after element D joins the team. One element joins the team, r+1=3.

As can be seen from figure (d) below, when another element needs to join the queue, an "overflow" will occur, but it is obvious that there are two empty storage units in the queue. This phenomenon is called "false overflow". The occurrence of this "false overflow" shows that the above storage method is defective. Then we will improve the above storage mode. A common improvement method is to adopt the circular queue structure, that is, the array is logically regarded as a ring connected from head to tail. When a new element enters the queue, the new element is stored in the next unit position of the ring structure. I won't explain it in detail here. I'll explain it in detail in the circular queue of this blog. You can turn over the directory and get there quickly.

basic operation

The circular queue has eight operations: initialization, destruction, queue entry, queue exit, empty judgment, full judgment, reading the team header elements, and outputting all the elements of the queue.

1. Initialization

The initialization of sequential queue only needs to make the head pointer and tail pointer point to the position of - 1. Pointing to - 1 is because we use a one-dimensional array to realize this sequential queue.

void InitQueue(SqQueue &Q)//Initialize queue
{
	Q.front = Q.rear = -1;
}

2. Destruction

The destruction operation is the same as the initialization operation. It's good to make the team head pointer and the team tail pointer point to - 1. You can add the judgment code of whether to destroy in front.

void DestroyQueue(SqQueue &Q)//Destroy queue
{
	char a;
	printf("Destroy queue( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'Y')
	{
		Q.front = Q.rear = -1;
		printf("Queue destroyed successfully\n");
	}
	else
		printf("Queue destruction failed\n");
}

3. Join the team

Queue entry means that the element enters the queue. Every time the element enters the queue, the queue end pointer rear will be + 1. It should be noted that the queue end pointer rear will be + 1 before entering. Put the element into the position pointed by the queue end pointer rear. This is just the opposite to the following queue exit operation.

We can add a code to confirm joining the team before joining the team. We can also add this when leaving the team. Here, we use getchar() to deal with the remaining characters.

bool EnQueue(SqQueue &Q)//Join the team
{
	char a;
	printf("Whether to join the team( Y/N):");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
		return false;
	if (QueueFull(Q))//Judge whether the queue is full. If the queue is full, you cannot join the queue. return false directly.
	{
		printf("The team is full and cannot join the team\n");
		return false;
	}
	printf("Please enter a number to join the team:");
	int x;
	scanf("%d", &x);
	Q.rear = Q.rear + 1;//The tail pointer moves forward one space
	Q.data[Q.rear] = x;//Put the element x into the queue position pointed to by the end of the queue pointer at this time
	printf("The elements of joining the team are%d\n", x);
	return true;
}

4. Out of the team

Outgoing is to delete the elements in the queue. Every time you exit the queue, the queue head pointer front will be + 1. It should be noted that this element will be deleted by directly moving the queue head pointer front one position forward. The same as joining the queue, the outgoing confirmation code can be added at the beginning.

bool DeQueue(SqQueue &Q)//Out of the team
{
	char a;
	printf("Out of line( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
		return false;
	if (QueueEmpty(Q))//Judge whether the queue is empty. If the queue is empty, you can't get out of the queue. return false directly.
		return false;
	printf("The elements of successful team exit are:%d\n",Q.data [Q.front+1]);
	Q.front = Q.front + 1;//The team head pointer moves forward one space
	return true;
}

5. Air judgment

To judge whether the team is empty is to judge whether the pointer at the end of the team and the pointer at the head of the team point to the same position.

bool QueueEmpty(SqQueue &Q)//Judge team empty
{
	return (Q.rear == Q.front);
}

6. Full sentence

To judge whether the queue is full, you can directly judge whether the tail pointer rear points to the last position of the queue. This sub judgment is sufficient. There is no need to add the condition that the head pointer rear points to - 1, because the false overflow is treated as a full queue.

bool QueueFull(SqQueue &Q)//Judge team full
{
	return (Q.rear == MaxSize - 1);
}

7. Read the header element

Before reading the queue header element, empty the queue first. Only when there are elements in the queue can the queue header be read. According to the concept, the queue header element is the element in front of the queue header pointer. Therefore, it is good to print Q.data[Q.front +1] directly.

bool GetHead(SqQueue &Q)//Read queue header element
{
	if (QueueEmpty(Q))
		return false;
	printf("The team head elements are:%d\n", Q.data [Q.front +1]);
	return true;
}

8. Output all elements of the queue

All the elements of the output queue only need to use a for loop to output one by one from the head element to the tail element.

bool print(SqQueue &Q)//Output queue element
{
	if (QueueEmpty(Q))
		return false;
	printf("The elements of the queue are:");
	for (int i = Q.front + 1; i <= Q.rear; i++)
	{
		printf("%d  ", Q.data[i]);
	}
	printf("\n");
	return true;
}

All codes and implementation results

#define MaxSize 10

#include<stdio.h>

typedef struct
{
	int data[MaxSize];
	int front, rear;
}SqQueue;

void InitQueue(SqQueue &Q)//Initialize queue
{
	Q.front = Q.rear = -1;
}

void DestroyQueue(SqQueue &Q)//Destroy queue
{
	char a;
	printf("Destroy queue( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'Y')
	{
		Q.front = Q.rear = -1;
		printf("Queue destroyed successfully\n");
	}
	else
		printf("Destroy failed\n");
}

bool QueueEmpty(SqQueue &Q)//Judge team empty
{
	return (Q.rear == Q.front);
}

bool QueueFull(SqQueue &Q)//Judge team full
{
	return (Q.rear == MaxSize - 1);
}

bool TakeQueue(SqQueue &Q)//Put elements in the queue
{
	int i;
	printf("Please enter the length of the queue to be created:");
	scanf("%d", &i);
	if (i > MaxSize || i < 0)
	{
		printf("Creation failed\n");
		return false;
	}
	printf("Please enter%d Number:",i);
	for (int j = 0; j < i; j++)
	{
		Q.rear = Q.rear + 1;
		scanf("%d", &Q.data[Q.rear]);
	}
	return true;
}

bool EnQueue(SqQueue &Q)//Join the team
{
	char a;
	printf("Whether to join the team( Y/N):");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
		return false;
	if (QueueFull(Q))
	{
		printf("The team is full and cannot join the team\n");
		return false;
	}
	printf("Please enter a number to join the team:");
	int x;
	scanf("%d", &x);
	Q.rear = Q.rear + 1;
	Q.data[Q.rear] = x;
	printf("The elements of joining the team are%d\n", x);
	return true;
}

bool GetHead(SqQueue &Q)//Read queue header element
{
	if (QueueEmpty(Q))
		return false;
	printf("The team head elements are:%d\n", Q.data [Q.front +1]);
	return true;
}
 
bool DeQueue(SqQueue &Q)//Out of the team
{
	char a;
	printf("Out of line( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
		return false;
	if (QueueEmpty(Q))
		return false;
	printf("The elements of successful team exit are:%d\n",Q.data [Q.front+1]);
	Q.front = Q.front + 1;
	return true;
}

bool Print(SqQueue &Q)//Output queue element
{
	if (QueueEmpty(Q))
		return false;
	printf("The elements of the queue are:");
	for (int i = Q.front + 1; i <= Q.rear; i++)
	{
		printf("%d  ", Q.data[i]);
	}
	printf("\n");
	return true;
}

int main()
{
	SqQueue(Q);
	InitQueue(Q);//Initialize queue
	TakeQueue(Q);//Put elements in the queue
	EnQueue(Q);//Join the team
	Print(Q);//Output queue element
	GetHead(Q);//Read queue header element
	DeQueue(Q);//Out of the team
	Print(Q);//Output queue element
	if (QueueEmpty(Q))//Judge team empty
		printf("Team air\n");
	else
		printf("The queue is not empty\n");
	if (QueueFull(Q))//Judge team full
		printf("Team full\n");
	else
		printf("The queue is not full\n");
	DestroyQueue(Q);//Destroy queue
	Print(Q);//Output queue element
	return 0;
}

2, Circular queue

The circular queue is implemented by one-dimensional array, and its data structure is defined as follows:

typedef struct //Define a queue
{
	int data[MaxSize];//Define an array
	int front, rear;//Defines the queue head pointer and the queue tail pointer
}SqQueue;

At the beginning, F and r will point to the position of 0. Unlike the sequential queue, F and r of the sequential queue point to the position of - 1. In the following figure, (a) is the empty queue generated by initialization, and (b) to (d) are the incoming and outgoing diagrams of circular queue. Queue elements a,b,c and D in an empty queue to obtain the queue state shown in (b); Then, a, B and C are queued in turn to obtain the queue state shown in (c); Finally, e and f join the queue to form the queue state shown in (d). It can be seen that when e joins the queue, the real is already 4. At this time, execute real = (real + 1)% MaxSize and then real = 0. Therefore, e is inserted into the unit with subscript position 0, which solves the problem of "false overflow".

be careful:
1. The circular queue is not really a ring queue, but a ring queue for the convenience of demonstration. Circular queue is an improvement of sequential queue, that is, the array is logically regarded as a ring with head and tail connected. When a new element enters the queue, the new element is stored in the next unit position of the ring structure.
2. Forward a cell position: front = (front+1)% MaxSize;
3. Forward one cell position: rear = (rear+1)% MaxSize;
4. There are three methods for circular queue to judge whether the queue is full / empty, depending on the writing method of the code. Here I use method 1. The details of the three methods are described below, which can be reached quickly by flipping the directory.

basic operation

Sequential queue is also eight operations: initialization, destruction, queue entry, queue exit, empty judgment, full judgment, reading the team header elements, and outputting all the elements of the queue.
The code part of the circular queue is not explained in detail, which is similar to the sequential queue.

1. Initialization

The initialization of sequential queue only needs to make the queue head pointer and queue tail pointer point to the position of 0

void InitQueue(SqQueue &Q)//Initialize queue
{
	Q.front = Q.rear = 0;//Initialize so that the pointer at the head of the queue and the pointer at the end of the queue point to 0
}

2. Destruction

The destroy operation is the same as initialization. Let the queue head pointer and queue tail pointer point to 0 again.

void DestroyQueue(SqQueue &Q)//Destroy queue
{
	char a;
	getchar();
	printf("Destroy queue( Y/N): ");
	scanf("%c", &a);
	if (a == 'Y')
	{
		Q.rear = Q.front=0;
		printf("Queue destroyed successfully\n");
	}
	else
		printf("Queue destruction failed\n");
}

3. Join the team

bool EnQueue(SqQueue &Q)//Join the team
{
	printf("Whether to join the team( Y/N):");
	getchar();
	char a;
	scanf("%c", &a);
	if (a == 'N')
		return false;
	if (QueueFull(Q))
	{
		printf("The team is full and cannot join the team\n");
		return false;
	}
	printf("Please enter a number to join the team:");
	int x;
	scanf("%d", &x);//Enter a number to join the team
	Q.rear = (Q.rear + 1) % MaxSize;//The tail pointer moves forward one space
	Q.data[Q.rear] = x;//Put the element x into the queue position pointed to by the end of the queue pointer at this time
	printf("The elements of joining the team are%d\n", x);
	return true;
}

4. Out of the team

bool DeQueue(SqQueue &Q)//Out of queue operation (delete a queue header element)
{
	char a;
	printf("Out of line( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
		return false;
	if (QueueEmpty(Q))
		return false;
	int x = Q.data[(Q.front + 1) % MaxSize];
	Q.front =(Q.front + 1) % MaxSize;
	printf("The out of team elements are:%d\n", x);
	return true;
}

5. Air judgment

Empty judgment of circular queue. Here we use to judge whether the queue head pointer and the queue tail pointer point to the same position.

bool QueueEmpty(SqQueue &Q)//Determine whether the queue is empty
{
	return (Q.front == Q.rear);
}

6. Full sentence

The above figure (b) is the case of full queue. Here I use method 1 to realize circular queue, so there will be a null position in the queue for empty and full queue judgment. The full judgment skill of method 1 is to judge whether the next position of the tail pointer is the position pointed by the head pointer.

bool QueueFull(SqQueue &Q)//Determine whether the queue is full
{
	return (Q.rear + 1) % MaxSize == Q.front;
}

7. Read the header element

bool GetHead(SqQueue &Q)//Get queue header element
{
	if (QueueEmpty(Q))
		return false;
	printf("The team head elements are:%d\n", Q.data[(Q.front + 1) % MaxSize]);
	return true;
}

8. Output all elements of the queue

bool Print(SqQueue &Q)//Output queue element
{
	if (QueueEmpty(Q))
		return false;
	printf("The elements of the queue are:");
	for (int i = (Q.front + 1) % MaxSize; i <= Q.rear; i++)
	{
		printf("%d  ", Q.data[i]);
	}
	printf("\n");
	return true;
}

All codes and implementation results

#define MaxSize 10

#include<stdio.h>

typedef struct 
{
	int data[MaxSize];//Storing queue elements in a static array
	int front, rear;//Queue head pointer and queue tail pointer
}SqQueue;

void InitQueue(SqQueue &Q)//Initialize queue
{
	Q.front = Q.rear = 0;//Initialize so that the pointer at the head of the queue and the pointer at the end of the queue point to 0
}

void DestroyQueue(SqQueue &Q)//Destroy queue
{
	char a;
	getchar();
	printf("Destroy queue( Y/N): ");
	scanf("%c", &a);
	if (a == 'Y')
	{
		Q.rear = Q.front=0;
		printf("Queue destroyed successfully\n");
	}
	else
		printf("Queue destruction failed\n");
}

bool QueueEmpty(SqQueue &Q)//Determine whether the queue is empty
{
	return (Q.front == Q.rear);
}

bool QueueFull(SqQueue &Q)//Determine whether the queue is full
{
	return (Q.rear + 1) % MaxSize == Q.front;
}

bool TakeQueue(SqQueue &Q)//Put elements in queue
{
	int i;
	printf("Please enter the queue length you want to create:");
	scanf("%d", &i);
	if (i > MaxSize - 1 || i < 0)
	{
		printf("Creation failed\n");
		return false;
	}
	printf("Please enter%d Number:", i);
	for (int j = 0; j < i; j++)
	{
		Q.rear = (Q.rear + 1) % MaxSize;
		scanf("%d", &Q.data[Q.rear]);
	}
	return true;
}

bool EnQueue(SqQueue &Q)//Join the team
{
	printf("Whether to join the team( Y/N):");
	getchar();
	char a;
	scanf("%c", &a);
	if (a == 'N')
		return false;
	if (QueueFull(Q))
	{
		printf("The team is full and cannot join the team\n");
		return false;
	}
	printf("Please enter a number to join the team:");
	int x;
	scanf("%d", &x);
	Q.rear = (Q.rear + 1) % MaxSize;//The tail pointer moves forward one space
	Q.data[Q.rear] = x;//Put the element x into the queue position pointed to by the end of the queue pointer at this time
	printf("The elements of joining the team are%d\n", x);
	return true;
}

bool GetHead(SqQueue &Q)//Get queue header element
{
	if (QueueEmpty(Q))
		return false;
	printf("The team head elements are:%d\n", Q.data[(Q.front + 1) % MaxSize]);
	return true;
}

bool DeQueue(SqQueue &Q)//Out of queue operation (delete a queue header element)
{
	char a;
	printf("Out of line( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
		return false;
	if (QueueEmpty(Q))
		return false;
	int x = Q.data[(Q.front + 1) % MaxSize];
	Q.front =(Q.front + 1) % MaxSize;
	printf("The out of team elements are:%d\n", x);
	return true;
}

bool Print(SqQueue &Q)//Output queue element
{
	if (QueueEmpty(Q))
		return false;
	printf("The elements of the queue are:");
	for (int i = (Q.front + 1) % MaxSize; i <= Q.rear; i++)
	{
		printf("%d  ", Q.data[i]);
	}
	printf("\n");
	return true;
}


int main()
{
	SqQueue Q;
	InitQueue(Q);//initialization
	TakeQueue(Q);//Put elements in the queue
	EnQueue(Q);//Join the team
	Print(Q);//Output queue element
	GetHead(Q);//Get queue header element
	DeQueue(Q);//Out of the team
	Print(Q);//Output queue element
	if (QueueEmpty(Q))//Determine whether the queue is empty
		printf("Queue is empty\n");
	else
		printf("Queue is not empty\n");
	if (QueueFull(Q))//Determine whether the queue is full
		printf("The queue is full\n");
	else
		printf("The queue is not full\n");
	DestroyQueue(Q);//Destroy queue
	Print(Q);
	return 0;
}

Three methods to judge whether the queue is full / empty by circular queue

If there is a space left when the queue is full, you can use method 1.

If all spaces in the queue are filled with elements, you can use method 2 and method 3.

a. Method 1 (leave a position)

Leave an empty position for the circular queue and let the queue head pointer point to the empty queue.

Queue full condition: the next position of the queue tail pointer is the queue head, that is, (Q.rear+1)%MaxSize == Q.front.
Air condition: Q.rear ==Q.front

Number of queue elements: (rear + maxsize front)% maxsize

b. Method 2 (with a counter)

If you want to fill all the spaces in the queue with elements, the judgment method of method 1 will fail when the queue is full and empty, because the tail pointer and head pointer point to the same position and cannot be judged. Therefore, we set an int variable size. The initial value of size is 0. When the queue performs a queue entry operation, size+1, when the queue performs a queue entry operation One out of line operation, size-1.

Queue full condition: size==MaxSize

Queue empty condition: size==0

c. Method 3 (set a judgment number)

In addition to method 2, we can also set a judgment number s to judge whether the queue is full or empty. The initial value of S is 0. When the queue performs an incoming operation, s=1; when the queue performs an outgoing operation, s=0. When rear == front, we can judge by just looking at the value of S. if s == 0, it indicates that the queue has performed an outgoing operation or the queue itself recently If s == 1, it indicates that the queue has been queued in the last time, then it can be concluded that the queue is full.

Full queue condition: front = = rear & & S = = 1

Air condition: front = = rear & & S = = 0

3, Chained queue (lead node)

Chained queue is a way of using linked list. Chained queue means that queue elements are stored in the form of linked list, and it is specified that only elements can be added from the tail of the linked list and removed from the head of the linked list.

The following defines the nodes of the chain queue and the chain queue. LinkNode emphasizes a node and LinkQueue emphasizes a queue.

typedef struct LinkNode//Chained queue node
{
	int data;//Data domain
	struct LinkNode *next;//Pointer field
}LinkNode;

typedef struct//Chain queue
{
	LinkNode *front, *rear;//Queue head pointer and queue tail pointer
}LinkQueue;

basic operation

The basic operations of chain queue include: initialization, destruction, queue entry, queue exit, empty judgment, reading queue header elements and outputting all queue elements.

1. Initialization

Open up a new node space, let the team head pointer and team tail pointer point to the node space, and then let the node point to the null pointer. This node is the head node.

void InitQueue(LinkQueue &Q)//initialization
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.front->next = NULL;//Make node point to null pointer
}

2. Destruction

Because the malloc function is used to apply for the space, the free function and the loop function are used to release the node space one by one.

bool DeleQueue(LinkQueue &Q)//Destroy queue
{
	char a;
	printf("Destroy queue( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Queue destruction failed\n");
		return false;
	}
	LinkNode *p, *q;//Create two new pointers
	p = Q.front;//Pointer p refers to the head node
	while (p != NULL)//When the pointer field of the head node is not 0, that is, it is not the tail of the chain
	{
		q = p->next;//Let q point to the subsequent nodes of the head node
		free(p);//The node space pointed to by the p pointer is released, but the p pointer still exists.
		p = q;//Let both p and q point to the subsequent node. At this time, both p and q pointers point to the next node. Just repeat the operation in this paragraph.
	}
	Q.rear = Q.front;//Let both the queue head pointer and the queue tail pointer point to the head node
	printf("Queue destroyed successfully\n");
	return true;
}

3. Join the team

Queue up at the end of the queue.

bool EnQueue(LinkQueue &Q)//Join the team
{
	char a;
	printf("Do you want to join the team( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Failed to join the team\n");
		return false;
	}
	int b;
	printf("Please enter the number of elements to join the queue:");
	scanf("%d", &b);
	for (int i = 0; i < b;i++)//Multiple queue operations with loops
	{
		int x;
		printf("Please enter the elements to be queued (one number at a time):");
		scanf("%d", &x);
		LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));//Use malloc function to apply for space for new node s
		if (s == NULL)
		{
			printf("Failed to join the team\n");
			return false;
		}
		s->data = x;//Put the entered number into the new node
		s->next = NULL;//Make the new node point to a null pointer
		Q.rear->next = s;//After the new node is inserted into the rear
		Q.rear = s;//Modify footer pointer
		printf("The elements of joining the team are:%d\n", x);
	}
	return true;
}

4. Out of the team

Exit the queue at the head of the queue

bool DeQueue(LinkQueue &Q)//Out of the team
{
	char a;
	printf("Out of line operation( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Team failure\n");
		return false;
	}
	if (Q.rear == Q.front)//Determine whether the team is empty
		return false;
	LinkNode *p = Q.front->next;//Create a new pointer to the node where the out of queue element is located
	int x = p->data;//Put the value of the first element in x
	printf("The out of team elements are:%d\n", x);
	Q.front->next = p->next;//Modify the next pointer of the header node
	if (Q.rear == p)//This is the last node out of the team
		Q.rear = Q.front;//Modify the real pointer
	free(p);//Frees the node space of the element pointed to by the pointer p
	return true;
}

5. Air judgment

Judge whether the team head pointer and the team tail pointer point to the same position

bool EmptQueue(LinkQueue &Q)//Air judgment
{
	if (Q.rear == Q.front)
	{
		printf("Empty queue\n");
		return true;
	}
	else
		printf("Is not an empty queue\n");
	return false;
}

6. Read the header element

bool FrontQueue(LinkQueue &Q)//Take team header element
{
	if (Q.rear == Q.front)
	{
		printf("Empty team, headless element\n");
		return false;
	}
	printf("The team head elements are:%d\n", Q.front->next->data);//Print the element value of the next node pointed to by the queue head pointer
	return true;
}

7. Output all elements of the queue

bool Print(LinkQueue &Q)//Output queue element
{
	if (Q.front == Q.rear)//Air judgment
	{
		printf("Queue is empty\n");
		return false;
	}
	LinkNode *p = Q.front->next;//Create a new pointer to the node where the queue head element is located
	printf("The elements of the queue are:");
	while (1)
	{
		printf("%d ", p->data);
		if (p == Q.rear)//Determine whether p points to the tail node
		{
			printf("\n");
			return true;
		}
		p = p->next;//Node p points to the next node
	}
}

All codes and implementation results

#include<stdio.h>
#include<stdlib.h>

typedef struct LinkNode//Chained queue node
{
	int data;//Data domain
	struct LinkNode *next;//Pointer field
}LinkNode;

typedef struct//Chain queue
{
	LinkNode *front, *rear;//Queue head pointer and queue tail pointer
}LinkQueue;

void InitQueue(LinkQueue &Q)//initialization
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.front->next = NULL;//Let the queue head pointer point to the null pointer
}

bool EnQueue(LinkQueue &Q)//Join the team
{
	char a;
	printf("Do you want to join the team( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Failed to join the team\n");
		return false;
	}
	int b;
	printf("Please enter the number of elements to join the queue:");
	scanf("%d", &b);
	for (int i = 0; i < b;i++)//Multiple queue operations with loops
	{
		int x;
		printf("Please enter the elements to be queued (one number at a time):");
		scanf("%d", &x);
		LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));//Use malloc function to apply for space for new node s
		if (s == NULL)
		{
			printf("Failed to join the team\n");
			return false;
		}
		s->data = x;//Put the entered number into the new node
		s->next = NULL;//Make the new node point to a null pointer
		Q.rear->next = s;//After the new node is inserted into the rear
		Q.rear = s;//Modify footer pointer
		printf("The elements of joining the team are:%d\n", x);
	}
	return true;
}

bool DeQueue(LinkQueue &Q)//Out of the team
{
	char a;
	printf("Out of line operation( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Team failure\n");
		return false;
	}
	if (Q.rear == Q.front)//Determine whether the team is empty
		return false;
	LinkNode *p = Q.front->next;//Create a new pointer to the node where the out of queue element is located
	int x = p->data;//Put the value of the first element in x
	printf("The out of team elements are:%d\n", x);
	Q.front->next = p->next;//Modify the next pointer of the header node
	if (Q.rear == p)//This is the last node out of the team
		Q.rear = Q.front;//Modify the real pointer
	free(p);//Frees the node space of the element pointed to by the pointer p
	return true;
}

bool FrontQueue(LinkQueue &Q)//Take the first element of the team
{
	if (Q.rear == Q.front)
	{
		printf("Empty team, headless element\n");
		return false;
	}
	printf("The team head elements are:%d\n", Q.front->next->data);//Print the element value of the next node pointed to by the queue head pointer
	return true;
}

bool EmptQueue(LinkQueue &Q)//Air judgment
{
	if (Q.rear == Q.front)
	{
		printf("Empty queue\n");
		return true;
	}
	else
		printf("Is not an empty queue\n");
	return false;
}

bool Print(LinkQueue &Q)//Output queue element
{
	if (Q.front == Q.rear)//Air judgment
	{
		printf("Queue is empty\n");
		return false;
	}
	LinkNode *p = Q.front->next;//Create a new pointer to the node where the queue head element is located
	printf("The elements of the queue are:");
	while (1)
	{
		printf("%d ", p->data);
		if (p == Q.rear)//Determine whether p points to the tail node
		{
			printf("\n");
			return true;
		}
		p = p->next;//Node p points to the next node
	}
}

bool DeleQueue(LinkQueue &Q)//Destroy queue
{
	char a;
	printf("Destroy queue( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Queue destruction failed\n");
		return false;
	}
	LinkNode *p, *q;//Create two new pointers
	p = Q.front;//Pointer p refers to the head node
	while (p != NULL)//When the pointer field of the head node is not 0, that is, it is not the tail of the chain
	{
		q = p->next;//Let q point to the subsequent nodes of the head node
		free(p);//The node space pointed to by the p pointer is released, but the p pointer still exists.
		p = q;//Let both p and q point to the subsequent node. At this time, both p and q pointers point to the next node. Just repeat the operation in this paragraph.
	}
	Q.rear = Q.front;//Let both the queue head pointer and the queue tail pointer point to the head node
	printf("Queue destroyed successfully\n");
	return true;
}

int main()
{
	LinkQueue Q;
	InitQueue(Q);//initialization
	EnQueue(Q);//Join the team
	FrontQueue(Q);//Take team header element
	Print(Q);//Output queue all elements
	DeQueue(Q);//Out of the team
	Print(Q);//Output queue all elements
	EmptQueue(Q);//Air judgment
	DeleQueue(Q);//Destroy queue
	Print(Q);//Output queue all elements
	return 0;
}


4, Chained queue (no leader node)

There is little difference between the chain queue of the leading node and the chain queue of the non leading node. The definition of the node of the chain queue and the chain queue is the same.

typedef struct LinkNode//Chained queue node
{
	int data;//Data domain
	struct LinkNode *next;//Pointer field
}LinkNode;

typedef struct//Chain queue
{
	LinkNode *front, *rear;//Queue head pointer and queue tail pointer
}LinkQueue;

1 initialization

Because there is no head node, the queue head pointer and queue tail pointer point to null pointers at the beginning.

void InitQueue(LinkQueue &Q)//initialization
{
	Q.front = Q.rear = NULL;
}

2. Destruction

bool DeleQueue(LinkQueue &Q)//Destroy queue
{
	char a;
	printf("Destroy queue( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Destroy failed\n");
		return false;
	}
	if (Q.front == NULL)
	{
		printf("Empty queue, destroy failed\n");
		return false;
	}
	if (Q.front == Q.rear)//Determine whether there is only one node in the queue
	{
		LinkNode *p = Q.front;//Create a new pointer to the unique node
		Q.front = NULL;
		Q.rear = NULL;
		free(p);
		printf("Queue destroyed successfully\n");
		return true;
	}
	LinkNode *p, *q;
	p = Q.front;//Let the p pointer point to the first node
	q = Q.front->next;//Let the q pointer point to the second node
	while (q != NULL)//Determine whether the q pointer points to the last node
	{
		free(p);
		p = q;//The p pointer points to the next node
		q = q->next;//The q pointer also points to the next node
	}
	Q.front = Q.rear = NULL;//Make the queue head pointer and queue tail pointer point to the null pointer
	printf("Queue destroyed successfully\n");
	return true;
}

3. Join the team

Since there is no header node, additional processing is required when the first element is queued. Let both the queue head pointer and the queue tail pointer point to the first node, and this node is a type of header node. It is just a header node with data elements.

bool EnQueue(LinkQueue &Q)//Join the team
{
	char a;
	printf("Do you want to join the team( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Failed to join the team\n");
		return false;
	}
	int j;
	printf("Please enter the number of elements to join the queue:");
	scanf("%d", &j);
	for (int i = 0; i < j;i++)
	{
		int x;
		LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));//Use malloc function to apply for space for new node s
		printf("Please enter the elements to be queued (one at a time):");
		scanf("%d", &x);
		s->data = x;//Put element into node s
		s->next = NULL;//Let node s point to a null pointer
		if (Q.front == NULL)//If the queue is empty, the first element in the queue needs additional processing
		{
			Q.front = s;
			Q.rear = s;
		}
		else//If the queue is not empty, you only need to operate the end of the queue pointer
		{
			Q.rear->next = s;//Change the pointer field of the node pointed to by the current queue tail pointer to the next node
			Q.rear = s;//The tail pointer points to the s node
		}
		printf("The elements of joining the team are:%d\n", x);
	}
	return true;
}

4. Out of the team

bool DeQueue(LinkQueue &Q)//Out of the team
{
	char a;
	printf("Out of line operation( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Team failure\n");
		return false;
	}
	if (Q.front == NULL)
	{
		printf("Team failure\n");
		return false;
	}
	LinkNode *p = Q.front;
	int x = p->data;
	Q.front = p->next;
	if (Q.rear == p)
	{
		Q.front = NULL;
		Q.rear = NULL;
	}
	free(p);
	printf("Team out succeeded. The team out elements are:%d\n",x);
	return true;
}

5. Air judgment

When the queue is empty, both the tail pointer and the head pointer point to the null pointer, so there are two methods to judge whether the queue is empty. You can judge whether the head pointer or the tail pointer points to the null pointer. The implementation codes of the two methods are as follows:

void IsEmpty1(LinkQueue &Q)//Empty judgment (team head pointer)
{
	if (Q.front == NULL)
		printf("Empty queue\n");
	else
		printf("Is not an empty queue\n");
}
void IsEmpty2(LinkQueue &Q)//Null judgment (tail pointer)
{
	if (Q.rear == NULL)
		printf("Empty queue\n");
	else
		printf("Is not an empty queue\n");
}

6. Read the header element

Because the queue head pointer points to the queue head element, you can directly output q.front - > data.

bool FrontQueue(LinkQueue &Q)//Read queue header element
{
	if (Q.front == NULL)
	{
		printf("Empty team, headless element\n");
		return false;
	}
	printf("The team head elements are:%d\n", Q.front->data);
	return true;
}

7. Output all elements of the queue

Traverse the output

bool Print(LinkQueue &Q)//Output queue element
{
	if (Q.front == NULL)
	{
		printf("Empty queue\n");
		return false;
	}
	LinkNode *s = Q.front;//The queue head pointer of the chain queue points to the queue head element, so here let the pointer s point to the node pointed to by the queue head pointer
	printf("The elements of the queue are:");
	while (1)
	{
		printf("%d ", s->data);
		if (s == Q.rear)
		{
			printf("\n");
			return true;
		}
		s = s->next;
	}
}

All codes and implementation results

#include<stdio.h>
#include<stdlib.h>

typedef struct LinkNode//Chained queue node
{
	int data;//Data domain
	struct LinkNode *next;//Pointer field
}LinkNode;

typedef struct//Chain queue
{
	LinkNode *front, *rear;//Queue head pointer and queue tail pointer
}LinkQueue;

void InitQueue(LinkQueue &Q)//initialization
{
	Q.front = Q.rear = NULL;
}

void IsEmpty1(LinkQueue &Q)//Empty judgment (team head pointer)
{
	if (Q.front == NULL)
		printf("Empty queue\n");
	else
		printf("Is not an empty queue\n");
}

void IsEmpty2(LinkQueue &Q)//Null judgment (tail pointer)
{
	if (Q.rear == NULL)
		printf("Empty queue\n");
	else
		printf("Is not an empty queue\n");
}

bool EnQueue(LinkQueue &Q)//Join the team
{
	char a;
	printf("Do you want to join the team( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Failed to join the team\n");
		return false;
	}
	int j;
	printf("Please enter the number of elements to join the queue:");
	scanf("%d", &j);
	for (int i = 0; i < j;i++)
	{
		int x;
		LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));//Use malloc function to apply for space for new node s
		printf("Please enter the elements to be queued (one at a time):");
		scanf("%d", &x);
		s->data = x;//Put element into node s
		s->next = NULL;//Let node s point to a null pointer
		if (Q.front == NULL)//If the queue is empty, the first element in the queue needs additional processing
		{
			Q.front = s;
			Q.rear = s;
		}
		else//If the queue is not empty, you only need to operate the end of the queue pointer
		{
			Q.rear->next = s;//Change the pointer field of the node pointed to by the current queue tail pointer to the next node
			Q.rear = s;//The tail pointer points to the s node
		}
		printf("The elements of joining the team are:%d\n", x);
	}
	return true;
}

bool Print(LinkQueue &Q)//Output queue element
{
	if (Q.front == NULL)
	{
		printf("Empty queue\n");
		return false;
	}
	LinkNode *s = Q.front;//The queue head pointer of the chain queue points to the queue head element, so here let the pointer s point to the node pointed to by the queue head pointer
	printf("The elements of the queue are:");
	while (1)
	{
		printf("%d ", s->data);
		if (s == Q.rear)
		{
			printf("\n");
			return true;
		}
		s = s->next;
	}
}

bool DeQueue(LinkQueue &Q)//Out of the team
{
	char a;
	printf("Out of line operation( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Team failure\n");
		return false;
	}
	if (Q.front == NULL)
	{
		printf("Team failure\n");
		return false;
	}
	LinkNode *p = Q.front;
	int x = p->data;
	Q.front = p->next;
	if (Q.rear == p)
	{
		Q.front = NULL;
		Q.rear = NULL;
	}
	free(p);
	printf("Team out succeeded. The team out elements are:%d\n",x);
	return true;
}

bool FrontQueue(LinkQueue &Q)//Read queue header element
{
	if (Q.front == NULL)
	{
		printf("Empty team, headless element\n");
		return false;
	}
	printf("The team head elements are:%d\n", Q.front->data);
	return true;
}

bool DeleQueue(LinkQueue &Q)//Destroy queue
{
	char a;
	printf("Destroy queue( Y/N): ");
	getchar();
	scanf("%c", &a);
	if (a == 'N')
	{
		printf("Destroy failed\n");
		return false;
	}
	if (Q.front == NULL)
	{
		printf("Empty queue, destroy failed\n");
		return false;
	}
	if (Q.front == Q.rear)//Determine whether there is only one node in the queue
	{
		LinkNode *p = Q.front;//Create a new pointer to the unique node
		Q.front = NULL;
		Q.rear = NULL;
		free(p);
		printf("Queue destroyed successfully\n");
		return true;
	}
	LinkNode *p, *q;
	p = Q.front;//Let the p pointer point to the first node
	q = Q.front->next;//Let the q pointer point to the second node
	while (q != NULL)//Determine whether the q pointer points to the last node
	{
		free(p);
		p = q;//The p pointer points to the next node
		q = q->next;//The q pointer also points to the next node
	}
	Q.front = Q.rear = NULL;//Make the queue head pointer and queue tail pointer point to the null pointer
	printf("Queue destroyed successfully\n");
	return true;
}

int main()
{
	LinkQueue Q;
	InitQueue(Q);//initialization
	EnQueue(Q);//Join the team
	Print(Q);//Output queue element
	FrontQueue(Q);//Output header element
	DeQueue(Q);//Out of the team
	Print(Q);//Output queue element
	IsEmpty1(Q);//Empty judgment (team head pointer)
	IsEmpty2(Q);//Null judgment (tail pointer)
	DeleQueue(Q);//Destroy queue
	Print(Q);//Output queue element
}


If there is anything you don't understand and there are errors in the text, you can contact me by private letter. Thank you very much.

If you think this blog is helpful to you, you can praise it.

Topics: data structure queue