数据结构-环形队列 C和C++的实现
队列:
含义:是一种先入先出(FIFO)的数据结构。
当我们把数据一个一个放入队列中。当我们需要用到这些数据时,每次都从队列的头部取出第一个数据进行处理。就像排队进场一样,先排队的人先进场。
结构如下图所示
环形队列:
含义:它是在写程序时候一种队列的特殊表达方式,把队列数据组中的最后一个元素和第一个元素相连构成环,所以称为环形队列。
优点:环形队列在C/C++编程中首元素出队后不需要把队列所有元素向前移动,而取代把把队首指针向后移动,由于其环形结构,在插入元素后队尾指针会循环到队首原来的位置。相对普通队列的出队操作减少了大量的运算量。
C语言
程序清单:
本例中包含三个文件:
(插入图片)
Queue.h:
#ifndef _QUEUE_H #define _QUEUE_H typedef unsigned char uint8_t; typedef int Elem; typedef struct circlequeue { int iLength; int iSize; int iHead; int iTail; Elem *Datas; }Queue; uint8_t Queue_Init(Queue* queue,int size); uint8_t Queue_Delete(Queue *queue); uint8_t isQueueEmpty(Queue *queue); uint8_t isQueueFull(Queue *queue); int Queue_size(Queue *queue); uint8_t Queue_push(Queue *queue,Elem data); Elem Queue_front(Queue *queue); Elem Queue_back(Queue *queue); uint8_t Queue_pop(Queue *queue); void Queue_printf(Queue *queue); #endif
Queue.c:
#include <stdlib.h> #include <stdio.h> #include "Queue.h" /*******************************************************/ /*******************************************************/ /**********************创建队列*************************/ /*******************************************************/ /*******************************************************/ uint8_t Queue_Init(Queue* queue,int size) { queue->iSize = size; queue->iLength = 0; queue->iTail=0; queue->iHead=0; queue->Datas = (Elem *)malloc(size*sizeof(Elem)); return 1; } /*******************************************************/ /*******************************************************/ /**********************删除队列*************************/ /*******************************************************/ /*******************************************************/ uint8_t Queue_Delete(Queue *queue) { free(queue->Datas); return 1; } /*******************************************************/ /*******************************************************/ /*********************队头队尾操作**********************/ /*******************************************************/ /*******************************************************/ static void QueueTailAdd(Queue *queue) { queue->iTail++; queue->iTail = queue->iTail % queue->iSize; } static void QueueHeadAdd(Queue *queue) { queue->iHead ++; queue->iHead = queue->iHead % queue->iSize; } /*******************************************************/ /*******************************************************/ /***********************队列判空************************/ /*******************************************************/ /*******************************************************/ uint8_t isQueueEmpty(Queue *queue) { if(queue->iLength == 0) { return 1; } return 0; } /*******************************************************/ /*******************************************************/ /***********************队列判满************************/ /*******************************************************/ /*******************************************************/ uint8_t isQueueFull(Queue *queue) { if(queue->iLength>=queue->iSize) { return 1; } return 0; } /*******************************************************/ /*******************************************************/ /*******************返回队列现有长度********************/ /*******************************************************/ /*******************************************************/ int Queue_size(Queue *queue) { return queue->iLength; } /*******************************************************/ /*******************************************************/ /********************往队尾放入元素*********************/ /*******************************************************/ /*******************************************************/ uint8_t Queue_push(Queue *queue,Elem data) { if(isQueueFull(queue)) { return 0; } queue->Datas[queue->iTail] = data; QueueTailAdd(queue); queue->iLength++; return 1; } /*******************************************************/ /*******************************************************/ /************获取队头第一个元素(不删除)***************/ /*******************************************************/ /*******************************************************/ Elem Queue_front(Queue *queue) { if(isQueueEmpty(queue)) { return 0; } return queue->Datas[queue->iHead]; } Elem Queue_back(Queue *queue) { if(isQueueEmpty (queue)) { return 0; } return queue->Datas[queue->iTail]; } /*******************************************************/ /*******************************************************/ /******************删除队列第一个元素*******************/ /*******************************************************/ /*******************************************************/ uint8_t Queue_pop(Queue *queue) { if(isQueueEmpty(queue)) { return 0;//queue empty } QueueHeadAdd(queue); queue->iLength--; return 1; } /*******************************************************/ /*******************************************************/ /*****************打印队列中的全部元素******************/ /*******************************************************/ /*******************************************************/ void Queue_printf(Queue *queue) { int i; int temp = queue->iHead; printf("queue datas:\r\n"); for(i=0;i<queue->iLength;i++) { printf("%d ",queue->Datas[temp++%queue->iSize]); } printf("\r\n"); }
main.c(用于测试):
#include <stdlib.h> #include <stdio.h> #include "Queue.h" int main(void) { int i; //queue(stack) Queue queue2[20]; //queue(heap) Queue *queue = (Queue*)malloc(sizeof(Queue)*20); //Queue Init Queue_Init(queue,20); Queue_Init(queue2,20); //queue1 printf("insert datas:(0-19)\r\n"); for(i=0;i<20;i++) { Queue_push(queue,i); } Queue_printf(queue); printf("delete datas(first 10):\r\n"); for(i=0;i<10;i++) { Queue_pop(queue); } Queue_printf(queue); printf("first data:%d\r\n",Queue_front(queue)); printf("queuesize = %d\r\n",Queue_size(queue)); //queue2 printf("\r\n"); printf("insert datas to queue2:(0-190,10interval)\r\n"); for(i=0;i<20;i++) { Queue_push(queue2,i*10); } Queue_printf(queue2); printf("delete datas(first 10):\r\n"); for(i=0;i<10;i++) { Queue_pop(queue2); } Queue_printf(queue2); //delete queue printf("\r\n"); printf("queue1 delete\r\n"); Queue_Delete(queue); free(queue); queue=0; printf("queue2 delete\r\n"); Queue_Delete(queue2); system("pause"); return 0; }
测试结果:
函数详解:
环形队列结构体:
在循环队列中,有以下参数
必要参数:
- 数据 *Datas;
- 对尾索引 iTail;
- 队头索引 iHead;
可选参数:
- 队列总大小 iSize;//队列最大存放量,防止不当操作造成堆栈溢出
- 队列现在的长度 iLength;//储存现在的长度减少运算量(不定义此参数可以通过队头队尾索引差值计算长度)
typedef struct circlequeue { int iLength; int iSize; int iHead; int iTail; Elem *Datas; }Queue;
创建队列:
- 设置队列的最大长度;
- 把队列中的其他参数清零;
- 为队列的数据区域申请内存;
uint8_t Queue_Init(Queue* queue,int size) { queue->iSize = size; queue->iLength = 0; queue->iTail=0; queue->iHead=0; queue->Datas = (Elem *)malloc(size*sizeof(Elem)); return 1; }
入队操作:
- 判断队列是否已满,满则无法插入,返回0插入失败;
- 往队尾插入数据
- 队尾索引增加
- 队列长度增加
uint8_t Queue_push(Queue *queue,Elem data) { if(isQueueFull(queue)) { return 0; } queue->Datas[queue->iTail] = data; QueueTailAdd(queue); queue->iLength++; return 1; }
出队操作(分为两部分)
出队细分一、获取队头元素但不删除
- 判断队列是否为空,空则获取失败返回0;
- 返回队列中队头索引指向元素
Elem Queue_front(Queue *queue) { if(isQueueEmpty(queue)) { return 0; } return queue->Datas[queue->iHead]; }
出队细分二、删除队头的元素但不返回其值
- 判断队列是否为空,空则删除失败;
- 增加队头索引;
- 减少队列长度;
uint8_t Queue_pop(Queue *queue) { if(isQueueEmpty(queue)) { return 0;//queue empty } QueueHeadAdd(queue); queue->iLength--; return 1; }
打印队列中的元素、
创建一个temp等于队头索引,后边打印中使用;
循环打印iLength(队列长度)个数据;
从队头(temp)指向的元素开始打印,每打印一个数据后temp++(指向下一个元素),(特别说明:temp%queue->iSize取余数,当temp索引超过最大长度时自动返回数组头开始打印,temp++%queue->iSize相当于两步1、temp%queue->iSize 2、temp++)
void Queue_printf(Queue *queue) { int i; int temp = queue->iHead; printf("queue datas:\r\n"); for(i=0;i<queue->iLength;i++) { printf("%d ",queue->Datas[temp++%queue->iSize]); } printf("\r\n"); }
C++语言
C++中思路和C基本类似,这里就不在赘述。上程序:
程序清单:
本部分包含三个文件:
(此处插入图)