队列的链式存储

文章详细介绍了链式存储结构在实现队列时的两种方式,包括带头结点和不带头结点的初始化、判空、入队和出队操作。通过示例代码展示了如何进行这些基本操作。

队列的链式存储

链式存储的结构

1、链式存储的结构

typedef int ElemType;

//链式队列结点的结构
typedef struct LinkNode {
	ElemType data;
	struct LinkNode* next;
}LinkNode;
//链式队列的结构
typedef struct {
	LinkNode* front;
	LinkNode* rear;
}LinkQueue;

2、单链表的结构对比

//单链表的结构
typedef int ElemType;
typedef struct LNode {
	ElemType data;
	struct LNode* next;//指向下一个结点 
}LNode, * LinkList;

两种初始化方式

1、带头结点的初始化

//初始化(带头结点)
void InitQueue(LinkQueue& Q) {
	//初始时 front、rear都指向头结点
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.front->next = NULL;
}
	//带头结点的判空
bool IsEmpty(LinkQueue Q) {
	if (Q.front == Q.rear)
		return true;
	else
		return false;
}

2、不带头结点的初始化

/初始化(不带头结点)
void InitQueue(LinkQueue& Q) {
	//初始时 front、rear都指向NULL
	Q.front = NULL;
	Q.rear = NULL;
}
	//不带头结点的判空
bool IsEmpty2(LinkQueue Q) {
	if (Q.front == NULL) 
		return true;
	else
		return false;
}

两种入队方式

1、带头结点的入队

//入队(带头结点)
void EnQueue(LinkQueue& Q, ElemType x) {
	LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));	//创建新结点
	s->data = x;
	s->next = NULL;
	Q.rear->next = s;   //新元素从队尾进入队列,因此将新结点插入到rear之后
	Q.rear = s;		//修改队尾指针,使队尾指针指向新元素
}

2、不带头结点的入队

//入队(不带头结点)
void EnQueue2(LinkQueue& Q, ElemType x) {
	LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
	s->data = x;
	s->next = NULL;
	if (Q.front == NULL) { //如果是空队列的情况,则插入的元素作为队列的第一个元素
		Q.front = s;	//修改队头队尾指针
		Q.rear = s;
	}
	else {			//新结点插入到rear结点之后
		Q.rear->next = s;
		Q.rear = s;
	}
}

两种出队方式

1、带头结点的出队

//出队(带头结点)
bool DeQueue(LinkQueue& Q, ElemType x) {
	if (Q.front == Q.rear)
		return false;  //空队
	LinkNode* p = Q.front->next;	//使p指向第一个结点,即要出队的结点
	x = p->data;			//用变量x返回队头元素
	Q.front->next = p->next;//修改头结点的next指针
	if (Q.rear == p)		//如果该出队元素是队列中最后一个元素,则将队列置为空队列
		Q.rear = Q.front;
	free(p);		//释放结点空间
	return true;
}
		//Q.front是头结点(第0个结点),Q.front->next是第一个结点,即要出队的结点

2、不带头结点的出队

//出队(不带头结点)
bool DeQueue2(LinkQueue& Q, ElemType x) {
	if (Q.front == Q.rear)
		return false;  //空队
	LinkNode* p = Q.front;		//p指向队头结点,即要出队的结点
	x = p->data;
	Q.front = p->next;
	if (Q.rear == p)
		Q.rear = NULL;
		Q.front = NULL;
	free(p);
	return true;
}
		//没有头结点的情况下,Q.front即为队头结点,即要出队结点
### 队列链式存储实现 队列是一种遵循先进先出(FIFO, First In First Out)原则的数据结构。其链式存储形式通过单链表实现,通常被称为链队列(Linked Queue)。为了提高操作效率,除了基本的节点外,还可以引入两个辅助指针——`front` 和 `rear` 分别指向队首和队尾。 以下是基于 C++ 的链队列数据结构定义及其核心功能实现: #### 1. 结构体定义 链队列由两部分组成:一个是表示节点的结构体 `Node`,另一个是用于管理整个队列的结构体 `Queue`。 ```cpp // 定义节点结构体 struct Node { int data; // 节点数据 struct Node* next; // 下一节点指针 }; // 定义队列结构体 struct Queue { struct Node* front; // 队首指针 struct Node* rear; // 队尾指针 }; ``` 上述代码中,`Node` 是链表的基本单元,而 `Queue` 则封装了队列的操作逻辑[^3]。 --- #### 2. 初始化队列 创建一个新的空队列时,需将 `front` 和 `rear` 均设置为空指针。 ```cpp void initialize(Queue* q) { q->front = nullptr; q->rear = nullptr; } ``` 此方法确保新队列处于初始状态,没有任何元素[^2]。 --- #### 3. 进队列 (Enqueue) 向队列中插入一个新元素时,将其添加至队尾,并更新 `rear` 指针。 ```cpp bool enqueue(Queue* q, int value) { struct Node* newNode = new Node(); if (!newNode) return false; // 内存分配失败 newNode->data = value; newNode->next = nullptr; if (q->rear == nullptr) { // 如果队列为空,则同时更新 front 和 rear q->front = q->rear = newNode; } else { // 否则仅更新 rear 及其链接关系 q->rear->next = newNode; q->rear = newNode; } return true; } ``` 该过程的时间复杂度为 O(1),得益于额外维护的 `rear` 指针[^1]。 --- #### 4. 出队列 (Dequeue) 从队列中移除并返回最前面的元素时,只需调整 `front` 指针即可。 ```cpp int dequeue(Queue* q) { if (q->front == nullptr) return -1; // 表示队列为空 struct Node* temp = q->front; int removedValue = temp->data; q->front = q->front->next; // 移动 front 指针 if (q->front == nullptr) q->rear = nullptr; // 若删除后队列变空,则重置 rear delete temp; // 释放被移除节点的空间 return removedValue; } ``` 同样地,由于有 `front` 指针的存在,这一操作也具有 O(1) 时间复杂度[^3]。 --- #### 5. 获取队列长度 可以通过增加一个整型成员变量 `size` 来实时跟踪当前队列中的有效元素数量。 ```cpp int getSize(Queue* q) { int count = 0; struct Node* current = q->front; while (current != nullptr) { count++; current = current->next; } return count; } ``` 或者直接在每次调用 `enqueue` 或 `dequeue` 方法时动态修改 `size` 成员变量[^1]。 --- #### 测试函数 下面是一个简单的测试程序,展示如何使用以上定义的功能。 ```cpp #include <iostream> using namespace std; // 上述定义省略... int main() { Queue q; initialize(&q); cout << "Enqueuing elements..." << endl; enqueue(&q, 10); enqueue(&q, 20); enqueue(&q, 30); cout << "Dequeuing elements:" << endl; cout << dequeue(&q) << endl; cout << dequeue(&q) << endl; cout << "Current size of the queue: " << getSize(&q) << endl; return 0; } ``` 运行结果会显示进队与出队的过程以及最终剩余的有效元素数目。 --- ### 总结 链队列利用单链表实现了灵活可扩展的 FIFO 数据结构。借助于显式的头尾指针 (`front`, `rear`) 设计,使得常见的入队和出队操作均能在常量时间内完成。此外,还可进一步优化以支持更多特性,比如自动扩容或线程安全访问等[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

封心心心心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值