队列 c语言实现

本文介绍了队列作为线性表的一种,其先进先出(FIFO)的特性,并探讨了队列的逻辑结构与物理存储方式,包括顺序表和链式存储。通过链式表示来描述队列,强调了队尾插入、队头删除的原则,并提供了C语言实现队列的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.导言

栈和队列是两种常见的线性表,栈因为只能在表的一端进行插入和删除,这种结构决定了栈后进先出的特性,队列也是一种受限的线性表,队列只能在表的一端进行插入,在表的另一端进行删除。允许插入的一端叫做队尾(rear),允许删除的一端被称之为队头(front)。这种结构决定了队列具有先进先出(FIFO)的特性.对队列来说,在我们日常生活中,随处可见。去食堂排队打饭,最早排队的人,最先拿着饭菜离开,典型的先进先出(当然了,对于插队这种事情,我也就呵呵了)、队列在程序设计中也经常出现,如实时系统中的事件处理,操作系统中的作业排队等。在我们学习数据结构过程中,对于任何一种数据结构我们必须从以下角度去考虑:数据与数据之间的逻辑关系,数据间的关系怎么表示,数据和数据间的关系怎么在计算机中表示。这也就是数据结构的逻辑结构,和物理结构(也叫数据的存储结构)。队列(queue)就逻辑结构而言,是一种一对一的线性关系,是受限的线性表,只能在表尾进行插入,在表头进行删除。而数据在计算机中存储,总共用两种方式,一种是顺序表,用一块连续的内存单位,来保存数据。这里数据间的关系是:逻辑结构相邻的数据,物理存储位置也相邻。另一种是链式存储,链式存储是把数据和指向数据关系的指针封装成一个节点,保存数据的叫做数据域,能体现数据间的关系的叫做指针域。


2.队列的定义
队列(queue)是一种先进先出(first in first out)(FIFO)的线性表。它只允许在表的一端进行插入,在表的另一端、进行删除.允许插入的一端称之为队尾(rear),允许删除的一端称之为队头(front).


3.队列的性质
队列只允许在表尾进行插入,在表头进行删除,所以,队列的这种结构决定了队列具有先进先出的性质,凡是具有先进先出特性的可以考虑用队列来实现。


4.队列的链式表示
队列是一种受限的线性表,所以队列在计算机中也有两种表示和存储方式:(1)顺序表示(2)链式表示,这里用链式表示来存储。用链表表示的队列称为链队列。因为队列在表尾进行插入 ,在队头进行删除,所以一个队列显然需要一个指向队尾和队头的指针(分别称之为队尾指针,和队头指针)才能唯一确定。和单链表一样,为了操作方便,我们给链队列设置一个头节点,并令头指针指向了头节点,所以链队为空的判断条件是头指针和尾指针都指向了头节点。队列的插入和删除就是线性表的插入和删除的特需情况,只允许在表头进行删除,在表尾进行插入。


5.实现代码

//Queue.h
#ifndef QUEUE_H
#define QUEUE_H
typedef int DataType;

//-----------------------单链表队列节点(QNode)------------------------------//

typedef struct QNode{
	
	DataType data;//存放数据的数据域
	QNode *next;//存放数据间关系的指针域next 指向下一节点

}QNode;

//-----------------------单链表队列--------队列的链式存储结构----------------//
typedef struct LinkQueue{
	QNode *front;//队头指针指向队头
	QNode *rear;//队尾指针,指向队尾
	QNode *head;//队列头节点指针,数据域为空,指针域指向数据的第一个数据元素节点(首元节点),当队列为空时(front == rear == head)设置此节点为了方便队列的各种操作

}LinkQueue;

//-----------------------单链表队列的基本操作-----------为了插入方便设置了头节点------//
//构造队列:init_queue(LinkQueue *queue):分配内存,初始化队列
bool  init_queue(LinkQueue *queue);

//队列判空:is_queue_empty(const LinkQueue * const queue):判断队列是否为空,front == rear == head;
bool is_queue_empty(const LinkQueue * const queue);

//队列长度:queue_length( const LinkQueue * const queue);
int queue_length( const LinkQueue * const queue);

//从队尾进行插入; queue_insert( LinkQueue *queue , const DataType data)
bool queue_insert( LinkQueue *queue, const DataType data);

//遍历队列,访问队列中的所有节点的数据域: bool queue_traverse(const LinkQueue * const queue)
bool queue_traverse(const LinkQueue * const queue);


//获取队头数据元素  front_data( const LinkQueue * const queue, DataType *data )
DataType front_data( const  LinkQueue* const queue);

//从队列中删除队头 delete_queue_front( LinkQueue *queue);
bool delete_queue_front( LinkQueue *queue);

//将队列清空 clear_queue( LinkQueue *queue);将队列中所有数据元素都清除,直到队列为空
bool clear_queue( LinkQueue *queue);

//销毁队列:destroy_queue(LinkQueue *queue);队列将不存在,从头到尾删除队列中的节点释放队列所指的内存
//bool destroy_queue(LinkQueue *queue);
 bool destroy_queue(LinkQueue *queue);

#endif




//---------------------------队列基本操作算法描述(c语言实现)------------------//
#include"Queue.h"
#include<stdlib.h>
#include<stdio.h>

//--------------构造队列:init_queue(LinkQueue *queue):分配内存,初始化队列--------------//
//功能:构造一个空队列queue
//函数参数:queue 为指向队列的指针
//返回值:构造成功 返回true(1),构造失败 返回false(0)
//时间复杂度:O(1)
//测试用例{queue == NULL ,queuef != NULL}

bool  init_queue(LinkQueue *queue){

	if( queue == NULL)//当参数为指针时要判空
		exit(-1);//为空,进程结束,异常退出

	//生成一个QNode 类型的头节点(此节点数据域data不包含任何数据,指针域next指向队列的第一个节点,
	//当队列为空时(是指队列任何已经存在,但队列中没有任何数据)queue->rear == queue->front == head;
	
	queue->head =(QNode*)malloc(sizeof(QNode));//为队列生成一个头节点(方便插入和删除)
	queue->head->data = 0;
	queue->head->next = NULL;//节点必须初始化 

	if( queue->head == NULL )//内存分配失败,进程异常退出
		exit(-1);

	else{
		queue->front = queue->rear = queue -> head;//构造了一个空队列
		return true;
	}

}



//------------------队列判空:is_queue_empty(const LinkQueue * const queue):判断队列是否为空,front == rear == head;----------//
//算法说明:判断队列是否为空,为空的条件是( queue->front == queue->head) && (queue->rear == queue ->head)
//参
#include #include #include //队列最大长度 #define MAX_QUEUE 1024 //偷懒,就用静态队列了 static int mQueue[MAX_QUEUE]; //队列插入 void InsertData(int **Front, int **Rear) { if (*Rear + 1 == *Front && (*Rear + 1 - MAX_QUEUE != *Front)) { //当队列数据已满,返回 puts("Queue Size Overflow!\n"); return; } else if (*Rear - mQueue > MAX_QUEUE) { //实现的是类似循环队列,但由于是静态线性队列(数组) //而不是用链表来实现的,所以到静态队列(数组)尾部,尾指针自动指向(数组)头部 *Rear = mQueue; } puts("Input Data:"); scanf("%d", *Rear); //输入数据后,尾指针后移 *Rear += 1; } //从头指针删除一个队列中的数据 void DeleteData(int **Front, int **Rear) { if (*Front == *Rear) { //头指针尾指针重合,队列空,不能删除,返回 puts("Queue Empty!\n"); return; } else if (*Front - mQueue > MAX_QUEUE) { //参考 Rear *Front = mQueue; } //从头指针删除一个数据 *Front += 1; } //显示队列数据 void ShowData(int **Front, int **Rear) { int *temp; for (temp=*Front; temp!=*Rear; temp++) { printf("%d --> ", *temp); } puts("\n"); } void usage(void) { puts("1. Insert Data"); puts("2. Delete Data"); puts("3. Show Data"); } int main(int argc, char **argv) { //头指针,尾指针 //队列的一个特性 First in first out FIFO int *pFront, *pRear; int op_code; //初始化队列,头指针和尾指针此时指向的地址相同 pFront = pRear = mQueue; while (1) { usage(); scanf("%d", &op_code); switch (op_code) { case 1: printf("%p\n", pFront); printf("%d\n", *pFront); InsertData(&pFront, &pRear); break; case 2: DeleteData(&pFront, &pRear); break; case 3: ShowData(&pFront, &pRear); break; default: break; } } return 0; }
好的,以下是一个用消息队列C语言实现线程间通信的简单例子。 假设有两个线程,一个是生产者线程,一个是消费者线程,需要通过消息队列实现通信。其中,生产者线程需要将数据写入消息队列,消费者线程则从消息队列中读取数据进行处理。 首先,需要定义一个消息结构体,例如: ```c struct message { long mtype; // 消息类型 char mtext[1024]; // 消息内容 }; ``` 然后,在生产者线程中,可以使用以下代码将数据写入消息队列: ```c #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> key_t key = ftok("path/to/file", 'a'); // 获取消息队列的键值 int msgid = msgget(key, 0666 | IPC_CREAT); // 创建消息队列 struct message msg; msg.mtype = 1; // 假设消息类型为1 strcpy(msg.mtext, "Hello, world!"); // 假设要发送的消息内容为 "Hello, world!" msgsnd(msgid, &msg, sizeof(msg), 0); // 将消息发送到消息队列中 ``` 在消费者线程中,可以使用以下代码从消息队列中读取数据: ```c #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> key_t key = ftok("path/to/file", 'a'); // 获取消息队列的键值 int msgid = msgget(key, 0666 | IPC_CREAT); // 获取消息队列的ID struct message msg; msgrcv(msgid, &msg, sizeof(msg), 1, 0); // 从消息队列中接收消息类型为1的消息 printf("Received message: %s\n", msg.mtext); // 处理接收到的消息 ``` 需要注意的是,消息队列中的消息类型必须是正整数,可以自定义。在发送消息时,需要指定消息类型;在接收消息时,需要指定要接收的消息类型。另外,需要在程序结束时删除消息队列,以释放资源: ```c msgctl(msgid, IPC_RMID, NULL); // 删除消息队列 ``` 以上就是一个简单的用消息队列C语言实现线程间通信的例子。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值