数据结构->链队

简介

链队(Linked Queue)是一种基于链表实现的队列数据结构。队列是一种先进先出(FIFO)的数据结构,即最先进入队列的元素最先被取出。链队的实现利用链表的特性,不像顺序队列需要提前确定队列的大小。

链队包含两个主要部分:节点(Node)和链表(Linked List)。每个节点都包含两个字段,一个用于存储数据元素,另一个用于指向下一个节点。链表的头部通常指向队列的前端,而尾部指向队列的后端。

链队的特点

  1. 动态大小: 与顺序队列不同,链队可以动态调整大小,无需预先分配固定大小的内存空间。这意味着可以根据需要灵活地添加或删除元素。

  2. 灵活插入和删除: 由于链队基于链表,插入和删除元素的操作更为灵活。入队和出队的时间复杂度为O(1)。

  3. 无需移动元素: 在链队中,不需要像顺序队列那样移动元素来保持队列的顺序。插入和删除只涉及修改节点的指针,而不涉及元素的搬移。

  4. 不需要预定义大小: 链队不需要事先定义队列的大小,因为链表的节点可以根据需要动态创建。

 基本操作

初始化(Initialization)

创建一个空链队,并初始化头尾指针。

// 初始化链队
void initQueue(struct LinkedQueue* queue) {
    queue->front = queue->rear = NULL;
}

入队(Enqueue) 

在链队的尾部插入一个新元素。这涉及创建一个新节点,并将尾指针指向这个新节点。如果链队是空的,头指针也要指向这个新节点。

// 入队操作
void enqueue(struct LinkedQueue* queue, int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    if (newNode == NULL) {
        printf("Memory allocation failed.\n");
        return;
    }
    newNode->data = data;
    newNode->next = NULL;

    if (isEmpty(queue)) {
        // 队列为空,新节点成为队头和队尾
        queue->front = queue->rear = newNode;
    } else {
        // 将新节点加入队尾
        queue->rear->next = newNode;
        queue->rear = newNode;
    }
}

出队(Dequeue) 

从链队的头部删除一个元素。这涉及将头指针指向下一个节点。如果链队在出队操作后为空,需要更新尾指针。

// 出队操作
int dequeue(struct LinkedQueue* queue) {
    if (isEmpty(queue)) {
        printf("Queue is empty.\n");
        return -1; // 表示队列为空
    }

    struct Node* frontNode = queue->front;
    int data = frontNode->data;

    if (queue->front == queue->rear) {
        // 队列中只有一个节点
        queue->front = queue->rear = NULL;
    } else {
        // 将队头指针指向下一个节点
        queue->front = frontNode->next;
    }

    free(frontNode);
    return data;
}

 判空(IsEmpty)

检查链队是否为空,即头指针是否为null。

// 判断链队是否为空
int isEmpty(struct LinkedQueue* queue) {
    return queue->front == NULL;
}

获取队头元素(Front)

// 获取队头元素
int frontElement(struct LinkedQueue* queue) {
    if (isEmpty(queue)) {
        printf("Queue is empty.\n");
        return -1; // 表示队列为空
    }
    return queue->front->data;
}

链队小结

链队的优点在于它能够动态地适应不同大小的队列,而无需预先分配固定大小的内存空间。然而,与顺序队列相比,链队可能在访问元素时有更多的指针操作,导致一些额外的开销。 

 

代码完整实现 

#include<stdlib.h>
#include<stdio.h>
#define MaxSize 10
typedef struct LinkNode{//链式队列节点 
	int data;
	struct LinkNode *next;
} LinkNode;
typedef struct{//链式队列 
	LinkNode *front,*rear;//链式队列头指针,尾指针 
}LinkQueue;
//初始化队列(带头节点) 
void InitQueue(LinkQueue &Q){
	Q.front=Q.rear=(LinkNode *)malloc(sizeof(LinkNode));//头指针和尾指针都指向头节点 
	Q.front->next=NULL;
} 
//判空
bool IsEmpty(LinkQueue Q){
	if(Q.front==Q.rear){
		return true;
	}
	return false;
} 
//入队(带头节点) 
void InsertQueue(LinkQueue &Q,int x){
	 LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
	 s->data=x;
	 s->next=NULL;
	 Q.rear->next=s;//新节点接到表尾指针之后 
	 Q.rear=s;//修改表尾指针 
} 
//(不带头节点)
void InsertQueue1(LinkQueue &Q,int x){
	 LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
	 s->data=x;
	 s->next=NULL;
	 if(Q.front==NULL){//在空队列中插入第一个元素 
	 	Q.front=s;
	 	Q.rear=s;
	 } 
	 else{
	 	Q.rear->next=s;
	 	Q.rear=s;
	 }
}
//出队(带头节点) Q.front指向头节点 
bool DeleteQueue(LinkQueue &Q,int &e){
	//判空
	if(Q.front==Q.rear){
		return false; 
	}	
	LinkNode *s;
	s=Q.front->next;//指向队列中第一个元素 
	e=s->data;
	Q.front->next=s->next;//修改头节点的next指针 
	if(Q.rear==s){
	   Q.rear=Q.front; 
	} 
	free(s);
	return true; 
} 
//出队(不带头节点) Q.front指向第一个元素节点
bool DeleteQueue1(LinkQueue &Q,int &e){
	if(Q.front==NULL){//判空 
		return false;
	} 
	LinkNode *s=Q.front;
	e=s->data;
	Q.front=s->next;
	if(s->next==NULL||Q.rear==s){
		Q.front=NULL;
		Q.rear=NULL;
	}
	free(s);
	return true;
} 
int main(){
	LinkQueue Q;
    InitQueue(Q);
}

 

  • 24
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

云里雾里!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值