Use a singly linked list with head and tail pointers to implement queue-related operations

Foreword: Before reading this blog, please read my previous blog sequence related operations . The content can help you understand this blog better.

Implementation of the queue

Here I use a singly linked list with head and tail pointers to simulate the function of the queue. This method is more convenient. The queue entry and dequeue operations can be implemented by using the tail insertion and head deletion (or head insertion and tail deletion) of the singly linked list respectively. First look at the structure definition of nodes and queues:


typedef int Qdatatype;

//结点
typedef struct Qnode {
    
    
	Qdatatype data;             
	struct Qnode* next;
}Qnode;

//队列
typedef struct Queue {
    
    
	
	//头尾指针
	struct Qnode*head;
	struct Qnode*tail;

}Queue;

Initialization-create a new node

Initialization: Create an empty queue
Create a new node: Define the data to be inserted as a node form of "struct Qnode"

//初始化
void Init(Queue* q)
{
    
    
	if (q == NULL)
		return;
	q->head = q->tail = NULL;

}



//创建新结点
struct Qnode* creatnode(Qdatatype val)
{
    
    
	struct Qnode* node = (struct Qnode*)malloc(sizeof(struct Qnode));
	node->data = val;
	node->next = NULL;
	return node;
}

Enqueue-End Insertion

The end node of the singly linked list is inserted as the end of the queue. Since we define the end node, the time complexity of this operation is O(1). Actual operation: If the queue exists and is empty, the head and tail pointers point to the new node at the same time; if the queue is not empty, the next pointer of the tail pointer points to the new node, and then the tail pointer is updated.

//入队-插入
void Queuepush(Queue* q,Qdatatype val)
{
    
    
	if (q == NULL)
		return;
	// 尾插
	struct Qnode*node = creatnode(val);
	if (q->head == NULL)
		q->head = q->tail = node;
	else
	{
    
    
		q->tail->next = node;
		q->tail = node;
	}
}

Module debugging screenshot:
Insert picture description here
Put 1, 2, 3, 4, and 5 into the team in turn. Valid elements of the queue: 1 2 3 4 5

Dequeue-Header Delete

Regarding the head node of the singly linked list as the head of the team for dequeue operation, the time complexity is O(1). Specific operation: update the head pointer to the next position of the lower original head node, and release the original head node at the same time. Here you need to pay attention to the function of the last two lines of code: if the pair has only one valid element, the head and tail pointers point to the same position. After the head pointer is updated and released, the tail pointer becomes a wild pointer and needs to be processed here.

//出队-头删
void Queuepop(Queue* q)
{
    
    
	if (q == NULL||q->head==NULL)
		return;
	//头删
	struct Qnode* next = q->head->next;
	free(q->head); 
	q->head = next;
	//若该队列只有一个结点,尾指针需要置空
	if (q->head == NULL)
		q->tail = NULL;
}

Module debugging screenshot: Insert picture description here
Three dequeue operations are performed on the original queue (1 2 3 4 5), the effective elements of the queue: 4 5

Get the head/tail element of the team

Directly return the data element pointed to by the head pointer or tail pointer, but the legitimacy of the queue needs to be judged before calling these two functions


//获取队首元素
Qdatatype Queuefront(Queue* q)
{
    
    
	return q->head->data;
}

//队尾元素
Qdatatype Queueback(Queue* q)
{
    
    
	return q->tail->data;
}

Determine whether the queue is empty

If the queue is empty, return 1;
if the queue is not empty, return 0.

//判断队列是否为空
int Queueempty(Queue* q)
{
    
    
	if (q->head == NULL)
		return 1;
	else
		return 0;
}

Complete code display

//队列

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>


typedef int Qdatatype;
typedef struct Qnode {
    
    
	Qdatatype data;
	struct Qnode* next;
}Qnode;

typedef struct Queue {
    
    
	
	//头尾指针
	struct Qnode*head;
	struct Qnode*tail;

}Queue;


//初始化
void Init(Queue* q)
{
    
    
	if (q == NULL)
		return;
	q->head = q->tail = NULL;

}

//创建新结点
struct Qnode* creatnode(Qdatatype val)
{
    
    
	struct Qnode* node = (struct Qnode*)malloc(sizeof(struct Qnode));
	node->data = val;
	node->next = NULL;
	return node;
}

//入队-尾插
void Queuepush(Queue* q,Qdatatype val)
{
    
    
	if (q == NULL)
		return;
	// 尾插
	struct Qnode*node = creatnode(val);
	if (q->head == NULL)
		q->head = q->tail = node;
	else
	{
    
    
		q->tail->next = node;
		q->tail = node;
	}
}

//出队-头删
void Queuepop(Queue* q)
{
    
    
	if (q == NULL||q->head==NULL)
		return;
	//头删
	struct Qnode* next = q->head->next;
	free(q->head); 
	q->head = next;
	//若该队列只有一个结点,尾指针需要置空
	if (q->head == NULL)
		q->tail = NULL;
}

//获取队首元素
Qdatatype Queuefront(Queue* q)
{
    
    
	return q->head->data;
}

//队尾元素
Qdatatype Queueback(Queue* q)
{
    
    
	return q->tail->data;
}

//判断队列是否为空
int Queueempty(Queue* q)
{
    
    
	if (q->head == NULL)
		return 1;
	else
		return 0;
}

void test()
{
    
    
	Queue q;
	Init(&q);
	Queuepush(&q, 1);
	Queuepush(&q, 2);
	Queuepush(&q, 3);
	Queuepush(&q, 4);
	Queuepush(&q, 5);
	Queuepush(&q, 6);
	Queuepush(&q, 7);
	Queuepush(&q, 8);

	while (!Queueempty(&q))
	{
    
    
		printf("%d ", Queuefront(&q));
		Queuepop(&q);
	}
	printf("\n");

}
int main()
{
    
    
	test();
	return 0;
}

operation result:Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_43962381/article/details/111851472