数据结构篇 - 链式队列

开源仓库:unittest

基本概念

我们可用日常生活中常见的链条结构来理解其概念。完整的链环条一条条相连,每条链环都有前后两个节点相连。有了一条长长的链子就可以在上面挂东西,无论是上衣、还是床单被褥都能挂。

上面Node1、Node2、Node3、Node4链条环都是独立的,独立的链条环是不能挂太多东西的。所以,它们需要被连接在一起。怎么办呢?生活中,每一个链条环都有一个切口,这个切口是能够用钳子掰开的,可以把新的链条环串接上,进而延长了链条长度。这在编码实现上,有一个很重要的概念叫结构体的自引用。

c 复制代码
typedef int QuDataType;
typedef struct QListNode
{
	struct QListNode* _next;
	QuDataType        _data;
}QueueNode; // 链式结构:表示队列

一个实例

理解了链式队列的基本概念,那如何编码实现呢?要实现链式队列,需要先定义一个链节点结构体,既然是队列就要有头有尾。用链节点结构体再去定义_front 和 _rear,这样,头节点有了,尾节点也有了,即实现的链式队列。

  • queue_linked_list.h
      头文件中定义了节点结构体,节点结构体相当于单独的一根链条环,上面有一个切口( _next ),还挂着一个东西(_data)。它们一起构成了基本的节点元素。为了让其能够与其它链条环连接在一块,采用结构体自引用方式实现。这时,新的(下一根)链条环也具有了切口和挂着的东西。
c 复制代码
#ifndef __QUEUE_LINKED_LIST_H
#define __QUEUE_LINKED_LIST_H

#ifdef __cplusplus
 extern "C" {
#endif
//FIFO数据结构
#include <stdio.h>
#include <malloc.h>
typedef int QuDataType;
typedef struct QListNode
{
 	struct QListNode* _next;
	QuDataType        _data;
}QueueNode; // 链式结构:表示队列

typedef struct LinkedListQueue
{
	QueueNode* _front;
	QueueNode* _rear;
}LinkedListQueue; // 队列的结构

void QueueInit(LinkedListQueue* q);                   // 初始化队列
void QueuePush(LinkedListQueue* q, QuDataType data);  // 队尾入队列
void QueuePop(LinkedListQueue* q);                    // 队头出队列
QuDataType QueueFront(LinkedListQueue* q);            // 获取队列头部元素
QuDataType QueueBack(LinkedListQueue* q);             // 获取队列队尾元素
int QueueSize(LinkedListQueue* q);                    // 获取队列中有效元素个数
int QueueEmpty(LinkedListQueue* q);                   // 检测队列是否为空,如果为空返回非零结果,如果非空返回0
void QueueDestory(LinkedListQueue* q);                // 销毁队列

#ifdef __cplusplus
}
#endif  
#endif 	/* __QUEUE_LINKED_LIST_H */
  • queue_linked_list.c
      一个数据入队列必须要先创建节点,新创建的节点会被放在队尾。这时,链条环的切口不会连接其它新的链条环了。所以,新创建的节点cur可直接将cur -> _next = NULL;
c 复制代码
#include "queue_linked_list.h"
//一个数据入队列必须要先创建节点
/**
 * ************************************************ 
 * @brief   创建节点并初始化此节点
 * @param   x               Param...
 * @return QueueNode*
 * ************************************************ 
 */
QueueNode* MyQueueNode(QuDataType data)    
{
	QueueNode* cur = (QueueNode *)malloc(sizeof(QueueNode));
	cur->_data = data;
	cur->_next = NULL;
	return cur;
}
/**
 * ************************************************ 
 * @brief   初始化队列结构
 * @param   q               Param...
 */
void QueueInit(LinkedListQueue* q) 
{
	q->_front = NULL;
	q->_rear  = NULL;
}
/**
 * ************************************************ 
 * @brief   队列尾部入数据
 * @param   q                Param...
 * @param   data             Param...
 */
void QueuePush(LinkedListQueue* q, QuDataType data)  
{
	QueueNode * cur = MyQueueNode(data);//先把创建好的节点传过来
	if (q->_front == NULL)              //若是队列本身为空,队列里就只有这一个节点,又为队列头又为队列尾
	{
		q->_front = q->_rear = cur; 
	}
	else
	{
		q->_rear->_next = cur;  //否则,链表尾插操作
		q->_rear = cur;
	}
}
/**
 * ************************************************ 
 * @brief   队列头部出数据
 * @param   q               Param...
 */
void QueuePop(LinkedListQueue* q)         
{
	if (q->_front == NULL)      //本身队列为空,不做操作
	{
		return;
    }
	QueueNode* tmp = q->_front->_next;   //先保留下一个节点,防止断链
	free(q->_front);
	q->_front = tmp;   //更新对列头部
}
/**
 * ************************************************ 
 * @brief   获取队列首部元素
 * @param   q               Param...
 * @return QuDataType
 * ************************************************ 
 */
QuDataType QueueFront(LinkedListQueue* q)   
{
	return q->_front->_data;
}
/**
 * ************************************************ 
 * @brief   获取队列尾部元素
 * @param   q               Param...
 * @return QuDataType
 * ************************************************ 
 */
QuDataType QueueBack(LinkedListQueue* q)
{
	return q->_rear->_data;
}
/**
 * ************************************************ 
 * @brief   判断队列是否为空
 * @param   q               Param...
 * @return int
 * ************************************************ 
 */
int QueueEmpty(LinkedListQueue* q)   
{
	return q->_front == NULL;   //为空,返回1
}
/**
 * ************************************************ 
 * @brief   获取队列中的元素个数
 * @param   q               Param...
 * @return int
 * ************************************************ 
 */
int QueueSize(LinkedListQueue* q)  
{
	QueueNode * cur;
	int count = 0;
	for (cur = q->_front; cur; cur = cur->_next)//循环遍历,计数即可
	{
		count++;
	}
	return count;
}
/**
 * ************************************************ 
 * @brief   销毁队列
 * @param   q               Param...
 */
void QueueDestory(LinkedListQueue* q)  
{
	if (q->_front == NULL)
	{
		return;
	}
	while (q->_front)
	{
		QueuePop(q);//对每一个元素迭代出队即可
	}
}

实例测试

c 复制代码
#define GOOGLE_GLOG_DLL_DECL           
#define GLOG_NO_ABBREVIATED_SEVERITIES  
#define GLOG_EXPORT  
#define GLOG_NO_EXPORT 
#include <gtest/gtest.h>             
#include <gtest/stub.h>              
#include <glog/logging.h>            
#include <iostream>
#include "queue_linked_list.h"             
using namespace std;       
using namespace std::chrono_literals;                           
/*-----------------BEGIN----------------*/ 
/**
 * ************************************************ 
 * @brief   链式队列测试函数
 * @return int
 * ************************************************ 
 */
int queue_linked_list_main(void)
{
	LinkedListQueue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
    LOG(INFO) << "the queue front value: "  << QueueFront(&q);
    LOG(INFO) << "the queue back  value: "  << QueueBack( &q);
    LOG(INFO) << "the queue size  value: "  << QueueSize( &q);
	QueuePop(&q);//出队列
    LOG(INFO) << "the queue front value: "  << QueueFront(&q);
    LOG(INFO) << "the queue back  value: "  << QueueBack( &q);
    LOG(INFO) << "the queue size  value: "  << QueueSize( &q);
	return 0;
}
TEST(TestSuite0, TEST1){
    LOG(INFO) << "\r\nUT >>>  queue_linked_list_main";
    queue_linked_list_main();
}
/*------------------END-----------------*/     
int gtest_main(int argc, char *argv[]){       
    google::InitGoogleLogging("UNITTEST");      
    google::SetStderrLogging(google::GLOG_INFO);   
    google::SetLogDestination(google::GLOG_INFO, ".//log//INFO_"); 
    google::EnableLogCleaner(2); 
    //init global variable                
                                               
    testing::InitGoogleTest(&argc, argv); 
    return RUN_ALL_TESTS();                
    google::ShutdownGoogleLogging();       
} 

测试报告

powershell 复制代码
Log file created at: 2026/02/12 18:04:27
Running on machine: DESKTOP-J6Q1P85
Running duration (h:mm:ss): 0:00:00
Log line format: [IWEF]yyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg
I20260212 18:04:27.791738 13304 test_case.cpp:102] 

UT >>>  queue_linked_list_main
I20260212 18:04:27.794257 13304 test_case.cpp:29] the queue front value: 1
I20260212 18:04:27.794257 13304 test_case.cpp:30] the queue back  value: 4
I20260212 18:04:27.795269 13304 test_case.cpp:31] the queue size  value: 4
I20260212 18:04:27.795269 13304 test_case.cpp:33] the queue front value: 2
I20260212 18:04:27.795269 13304 test_case.cpp:34] the queue back  value: 4
I20260212 18:04:27.795269 13304 test_case.cpp:35] the queue size  value: 3
I20260212 18:04:27.797263 13304 test_case.cpp:106] 
相关推荐
仰泳的熊猫3 小时前
题目1466:蓝桥杯基础练习VIP-字符串对比
数据结构·c++·算法·蓝桥杯
Renhao-Wan3 小时前
Java算法实践(二):堆与PriorityQueue实战
java·数据结构·算法
@––––––3 小时前
力扣hot100—系列7-二分查找
数据结构·算法·leetcode
你撅嘴真丑3 小时前
第九章-竞赛题目选讲-跳舞机
数据结构·算法
鲨鱼吃橘子4 小时前
C++刷题--递归回溯剪枝(二)
开发语言·数据结构·c++·算法·leetcode·深度优先·剪枝
666HZ66616 小时前
数据结构4.0 串
c语言·数据结构·算法
你撅嘴真丑17 小时前
蛇形填充数组 与 查找最接近的元素
数据结构·c++·算法
blackicexs18 小时前
第四周第四天
数据结构·c++·算法
Pluchon18 小时前
硅基计划4.0 算法 简单实现B树
java·数据结构·b树·算法·链表