C language data structure - queue

Posted by mistercoffee on Sat, 22 Jan 2022 21:14:58 +0100

1, Basic concepts of queue

(1) Definition: a linear table that can only be inserted at one end of the table and deleted at the other end of the table.
(2) Features: first in first out

The schematic diagram is as follows:

2, Queue of sequential storage structure

Dynamic diagram of sequential queue with 6 storage spaces

2.1 "false overflow" problem of sequential queue

① False overflow
The sequential queue is unable to perform queue in operation although there is storage space after multiple queue in and out operations.

② How to solve the false overflow problem of sequential queue?
There are four methods:
1) adopt circular queue;
2) set the maximum number of elements of the sequential queue according to the maximum possible number of incoming operations;
3) modify the out of queue algorithm to move the remaining data elements in the queue to the head of the queue after each out of the queue;
4) Modify the queue joining algorithm and add judgment conditions. In case of false overflow, move the data elements in the queue to the opposite end, and then complete the queue joining operation.

3, Representation and implementation of sequential cyclic queue

3.1 basic principle of sequential cyclic queue

 The storage space used by the sequential queue is constructed into a logically end-to-end circular queue. When rear and front achieve MaxQueueSize-1 After that, it will automatically reach 0 when moving forward one position.

3.2. Queue empty and full judgment of sequential cyclic queue

New problem: in the circular queue, the empty queue feature is front=rear; When the team is full, there will also be front=rear; The judgment conditions will be ambiguous!
There are three solutions:
① Use a counter to record the number of elements in the queue (i.e. queue length);
Team full: count > 0 & & rearfront; countMaxQueueSize
Team empty: count0
② Add a flag bit, set 0 when leaving the team and 1 when entering the team, then you can identify the current situation of front=rear
Team full: tag1 & & rearfront
Team empty: tag0 & & rearfront
③ One less storage unit
Queue full: front = = (rear+1)%MaxQueueSize
Air: rearfront

3.3 implementation of sequential cyclic queue

//The structure of sequential cyclic queue is defined as follows:
typedef struct
{
	DataType queue[MaxQueueSize];
	int rear;  //Tail pointer
	int front;  //Queue head pointer
	int count;  //Counter
} SeqCQueue; 

//(1) Initialize queueinitiate
void QueueInitiate(SeqCQueue *Q)
{
	Q->rear = 0;		
	Q->front = 0;
	Q->count = 0;
}

//(2) Non empty no QueueNotEmpty(Q)
//Judge whether the circular queue Q is not empty, return 1 if it is not empty, otherwise return 0
int QueueNotEmpty(SeqCQueue Q)
{
	if(Q.count != 0)	return 1;
	else return 0;
}

//(3) QueueAppend(Q, x)
//Insert the data element value x into the tail of the sequential cyclic queue Q, and return 1 for success and 0 for failure
int QueueAppend(SeqCQueue *Q, DataType x)
{
	if(Q->count > 0 && Q->rear == Q->front)
	{	
		printf("The queue is full and cannot be inserted! \n");
		return 0;
	}
	else
	{	
		Q->queue[Q->rear] = x;
		Q->rear = (Q->rear + 1) % MaxQueueSize;
		Q->count++;
		return 1;
	}
}

//(4) Out of queue QueueDelete(Q, d)
//Delete the queue header element of the sequential cyclic queue Q and assign it to d. if it succeeds, it returns 1 and if it fails, it returns 0
int QueueDelete(SeqCQueue *Q, DataType *d)
{
	if(Q->count == 0)
	{	printf("The queue is empty. No data elements are out of the queue! \n");
		return 0;
	}
	else
	{	*d = Q->queue[Q->front];
		Q->front = (Q->front + 1) % MaxQueueSize;
		Q->count--;
		return 1;
	}
}

//(5) Get queue header data element QueueGet(Q, d)
int QueueGet(SeqCQueue Q, DataType *d)
{
	if(Q.count == 0)
	{
		printf("The queue is empty and no data elements are available! \n");
		return 0;
	}
	else
	{
		*d = Q.queue[Q.front];
		return 1;
	}
}

4, Queue of chain storage structure

Storage structure of chain queue
The queue head pointer of the chain queue points to the current queue head node of the queue; End of queue pointer refers to the current end of queue node

The structure of chain queues without leading nodes is as follows:

//The node structure can be defined as follows:
typedef struct qnode
{
	DataType data;
	struct qnode *next;
} LQNode; 	
					
//Structure types of queue head pointer front and queue tail pointer rear:
typedef struct
{
	LQNode *front;	//Queue head pointer					
	LQNode *rear;	//Tail pointer					
} LQueue;

//(1) Initialize queueinitiate
void QueueInitiate(LQueue *Q)
{
	Q->rear = NULL;	                //Queue head pointer
	Q->front = NULL;	                //Tail pointer
}

//(2) Non empty no QueueNotEmpty(Q)
int QueueNotEmpty(LQueue Q)
{
	if(Q.front == NULL) return 0;
	else return 1;
}

//(3) QueueAppend(Q, x)
int QueueAppend(LQueue *Q, DataType x)
{
	LSNode *p;
 	p = (LQNode *)malloc(sizeof(LQNode)) ; 
	p->data = x;
	p->next = NULL;
	if(Q->rear != NULL) Q->rear->next = p;  //When the queue is not empty, a new node is added at the end of the queue
	Q->rear = p;  //Modify tail pointer
	if(Q->front == NULL) Q->front = p; //Modify the queue header pointer when the queue was originally empty
	if(Q->front==NULL){Q->rear= p; Q->front= p;}
	else {
	 	Q->rear->next = p; 	 Q->rear = p; 
	}
	return 1;
}

//(4) Out of queue QueueDelete(Q, d)
int QueueDelete(LQueue *Q, DataType *d)
{
	LQNode *p;
	if(Q->front == NULL)
	{	
		printf("The queue is empty. No data elements are out of the queue! \n");	
		return 0;
	}
	else
	{	
		*d = Q->front->data;
		p = Q->front;
		Q->front = Q->front->next;
		//There is only one node. After deletion, the queue is empty. Modify the tail pointer
		if(Q->front == NULL) Q->rear = NULL; 				
		free(p);
		return 1;
	}
}

//(5) Get queue header data element QueueGet(Q, d)
int QueueGet(LQueue Q, DataType *d)
{
	if(Q.front == NULL)
	{	printf("The queue is empty. No data elements are out of the queue! \n");
		return 0;
	}
	else
	{
		*d = Q.front->data;
		return 1;
	}
}

5, Priority queue: queue with priority.

5.1 main differences between priority queue and general queue

The out of queue operation of priority queue is not to get the queue head element out of the queue, but to get the element with the highest priority out of the queue.

struct DataType   
{                    
	 ElemType elem;     //data elements	
     int priority;      //priority
};

/*Out of queue operation
(The element with the highest priority is out of the queue and returned by the function. When the priority is the same, it is out of the queue according to the first in first out principle. Take the element with the highest priority in the order priority queue (similar to the algorithm)*/
int QueueDelete(SeqPQueue *Q, DataType *d)
//Delete the highest priority element in priority queue Q
{
	DataType min;
	int minIndex, i;
 	if(Q->size <= 0)
	{
		printf("The queue is empty. No data elements are out of the queue! \n");
		return 0;
	}	
	else
	{	
		min = Q->queue[0];
		minIndex = 0;
		for(i = 1; i < Q->size; i++){
	        if(Q->queue[i].priority < min.priority)
			{	
				min = Q->queue[i];
				minIndex = i;
			}
		}
 		*d = Q->queue[minIndex];
		for(i = minIndex+1; i < Q->size; i++){
			Q->queue[i-1] = Q->queue[i];
		}
 
		Q->size--;		
		return 1;
	}
}

//Take the element with the highest priority
int QueueGet(SeqPQueue *Q, DataType *d)
{
	DataType min;
	int minIndex i;
	if(Q->size<=0)
	{
		printf("")
		return 0;
	}
	else
	{
		min=Q->queue[0];
		minIndex =0;
		for(i=1;i<Q->size;i++)
		if(Q->queue[i].priority<min.priority)
		{
			min=Q->queue[i];
			minIndex =i;
		}
	*d=Q->queue[minIndex];
	return 1;
	}
}

Topics: Algorithm data structure linked list queue