队列算法的讲解

队列的定义
队列示意图
队列代码

队列算法的讲解

队列算法目前还是使用得比较多的一种数据结构,比如Linux的内核监测cpu性能,一些大型的项目需要对数据进行先后采集的,等等,都基本上使用队列比较方便,今天讨论的是队列的一般性数组性质的用法。

队列的定义

队列是一种数据结构,特点是“先进先出(FIFO)”,就类似于我们排队一样,所以队列在同步数据中还是有一定的优势的,因为必须等到前一个数据处理完成之后,才能进行下一步的处理。队列被广发使用到线程同步,进程同步等情形。

队列的示意图

在这里插入图片描述

队列的代码

本次使用较为简单的项目管理,调用Makefile的简单来管理编译,具体包含的源码文件有四个:

1.  main.c         ------ 项目调用的主入口文件
2.  queue.c        ------ 队列的数据结构实现文件
3.  queue.h        ------ 队列的数据结构声明文件
4.  Makefile       ------ 项目编译管理文件

queue.h 文件的代码

#ifndef __QUEUE_H__
#define __QUEUE_H__

typedef struct reg_Queue
{
	int front;
	int rear;
	int size;
	unsigned int capacity;
	int *array;

}Queue, *PQueue;

/* create a queue and init date. */
PQueue create_queue(unsigned int capacity);

/* Destory a queue. */
void destory_queue(PQueue queue);

/* Add a data into queue. */
int add_to_queue(PQueue queue, int item);

/* Remove a data from a queue. */
int delete_from_queue(PQueue queue);

/* Get the front position data. */
int get_front_item(PQueue queue);

/* Get the rear position data. */
int get_rear_item(PQueue queue);

/* Judge whether the queue is full. */
int is_queue_full(PQueue queue);

/* Judge whether the queue is empty. */
int is_queue_empty(PQueue queue);

#endif //__QUEUE_H__ 


queue.c 文件的代码

#include <stdlib.h>
#include <unistd.h>
#include "queue.h"

#define TRY_MAX_TIMES    3

PQueue create_queue(unsigned int capacity)
{
	PQueue queue = NULL;
	unsigned char uctries = TRY_MAX_TIMES;
	
	while(NULL == (queue = (PQueue)malloc(sizeof(Queue))) && uctries > 0)
	{
		usleep(10);
		uctries--;
	}

	if(NULL == queue)
	{
		return NULL;
	}

	uctries = 3;
	while(    NULL == (queue->array = (int*)malloc(capacity * sizeof(int))) 
		   && uctries > 0)
	{
		usleep(10);
		uctries--;
	}

	if(NULL == queue->array)
	{
		free(queue);
		queue = NULL;
		return NULL;
	}

	queue->capacity = capacity;
	queue->front = 0;
	queue->size = 0;
	queue->rear = capacity - 1;

	return queue;
}


void destory_queue(PQueue queue)
{
	if(NULL == queue)
	{
		return;
	}

	if(NULL != queue->array)
	{
		free(queue->array);
		queue->array = NULL;
	}

	free(queue);
	queue = NULL;
}


int add_to_queue(PQueue queue, int item)
{
	if(NULL == queue || NULL == queue->array)
	{
		return -1;
	}

	if(is_queue_full(queue))
	{
		return -1;
	}

	queue->rear = (queue->rear + 1) % (queue->capacity);
	queue->array[queue->rear] = item;
	queue->size++;

	return 0;
}

int delete_from_queue(PQueue queue)
{
	if(NULL == queue || NULL == queue->array)
	{
		return -1;
	}

	if(is_queue_empty(queue))
	{
		return -1;
	}

	int item = queue->array[queue->front];
	queue->front = (queue->front + 1) % (queue->capacity);
	queue->size++;
	
	return item;
}

int get_front_item(PQueue queue)
{
	if(NULL == queue || NULL == queue->array)
	{
		return -1;
	}

	if(is_queue_empty(queue))
	{
		return -1;
	}

	return queue->array[queue->front];
}

int get_rear_item(PQueue queue)
{
	if(NULL == queue || NULL == queue->array)
	{
		return -1;
	}

	if(is_queue_empty(queue))
	{
		return -1;
	}

	return queue->array[queue->rear]; 

}

int is_queue_full(PQueue queue)
{
	if(NULL == queue)
	{
		return -1;
	}

	return (queue->size == queue->capacity);
}

int is_queue_empty(PQueue queue)
{
	if(NULL == queue)
	{
		return -1;
	}

	return (queue->size == 0);
}

main.c 文件的代码

#include <stdio.h>
#include "queue.h"

#ifdef DEBUG_PRINT
#define DEBUG_INFO(fmt,...) fprintf(stderr, "\n"fmt"\n", ##__VA_ARGS__)
#else
#define DEBUG_INFO(fmt,...)
#endif 

int main(int argc, const char *argv[])
{
	PQueue queue = create_queue(10);
	if(NULL == queue)
	{
		DEBUG_INFO("create queue failed");
		return -1;
	}

	add_to_queue(queue, 10);
	add_to_queue(queue, 20);
	add_to_queue(queue, 30);
	add_to_queue(queue, 40);
	add_to_queue(queue, 50);

	DEBUG_INFO("front: %d", get_front_item(queue));
	DEBUG_INFO("rear: %d", get_rear_item(queue));

	delete_from_queue(queue);


	DEBUG_INFO("front: %d", get_front_item(queue));
	DEBUG_INFO("rear: %d", get_rear_item(queue));

	destory_queue(queue);
	
	
	return 0;
}

Makefile 文件的代码


TARGET=main


${TARGET}:main.o queue.o queue.h
	gcc main.c queue.c -o $@ -DDEBUG_PRINT

main.o:main.c queue.c queue.h
	gcc -c $< -o $@

queue.o:queue.c queue.h
	gcc -c $< -o $@ 

.PHONY:clean
clean:
	rm ${TARGET} -rvf 

.PHONY:disclean
disclean:
	rm *.o ${TARGET} -rvf


运行结果

在这里插入图片描述

总结

本次使用的队列结构是有局限性和代码的严谨性的问题。比方说,当前的代码使用的是数组方式的队列结构,那就局限于队列的大小,只能在规定的大小才能正常使用。然后就是代码严谨性的问题,当前代码中的两个函数:

/* Get the front position data. */
int get_front_item(PQueue queue);

/* Get the rear position data. */
int get_rear_item(PQueue queue);

它的实现为:

int get_front_item(PQueue queue)
{
	if(NULL == queue || NULL == queue->array)
	{
		return -1;
	}

	if(is_queue_empty(queue))
	{
		return -1;
	}

	return queue->array[queue->front];
}

int get_rear_item(PQueue queue)
{
	if(NULL == queue || NULL == queue->array)
	{
		return -1;
	}

	if(is_queue_empty(queue))
	{
		return -1;
	}

	return queue->array[queue->rear]; 

}

可以看到,当前我们使用的数组保存类型是 **有符号整形 **的数据,那么出错或者队列为空/满 的情况下,返回值为 -1,这是有很大的问题的,因为我们的数组中也是可以保持 -1 这个数值的,所以有那么一点不太严谨的做法,读者可以自行进行修改。个人建议的修改是使用结构体来加以判断,或者使用全局变量进行错误判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值