用数组实现队列--静态队列

/*
  一、关于静态队列的约定(目的是在C语言中描述方便)
  1.定义:和栈相反,队列是一种先进先出的线性表,它只允许在表的一端进行插入,在另一端进行删除元素。在队列中,允许插入的一端叫队尾,允许删除的一端较队头,即入队只能从队尾入,出队只能从队头出。
  
  2.初始化建空队列时,令front=rear=0;入队时,队尾指针rear增1;出队时队头指针增1。在非空队列中,队头指针front始终指向队列头元素,而队尾指针rear始终指向队列尾元素的下一个位置。
  
  3.在C语言中不能使用动态分配的一维数组来实现循环队列。如果用户程序中有循环队列,则必须为它设定一个最大队列长度,若用户无法预估所用队列最大长度,则宜采用链队列。
*/

#include "ArrayQueue.h"

void arrayQueueCreat(struct arrayQueue * qQ,int lengh)
{
	qQ->pBase =(int *)malloc(sizeof(int)*lengh);
	if( NULL == qQ->pBase )
	{
		printf("arrayQueueCreat(): malloc failed!\n");
		exit(-1);	
	} 
	qQ->arrayLen = lengh;
	qQ->queueLen = 0;
	qQ->front = 0;
	qQ->rear = 0;
}
int arrayQueueIsFull(struct arrayQueue * qQ)
{
	if( qQ->front == (qQ->rear+1)%(qQ->arrayLen) )
	    return 1;
	else
	    return 0;
}

int arrayQueueIsEmpty(struct arrayQueue * qQ)
{
	if( qQ->front == qQ->rear )
	    return 1;
	else
	    return 0;
}

//入队
int enArrayQueue(struct arrayQueue * qQ,int val)
{
	if( 1 == arrayQueueIsFull(qQ) )
	{
	    printf("the array queue is full\n");	
	    return 0;
	}
	qQ->pBase[qQ->rear] = val;//在队尾入
	qQ->rear = (qQ->rear+1)%(qQ->arrayLen);
	qQ->queueLen++;
	return 1;
}

//出队
int outArrayQueue(struct arrayQueue * qQ,int * pVal)
{
	if( 1 == arrayQueueIsEmpty(qQ) )
	{
	     printf("the array queue is empty\n");	
	    return 0;
	}
	*pVal = qQ->pBase[qQ->front];//在队头出
	qQ->front = (qQ->front+1)%(qQ->arrayLen);
	qQ->queueLen--;
	return 1;
}

void traverseArrayQueue(struct arrayQueue * qQ)
{
	int i=0;
	i = qQ->front;//从队头开始遍历
	while( i != qQ->rear )
	{
		printf("qQ->pBase[%d] = %d\n",i,qQ->pBase[i]);
		i = (i+1)% (qQ->arrayLen);
	}
        printf("\n");
	return;
}

相关头文件:

#ifndef ARRAYQUEUE_H
#define ARRAYQUEUE_H


#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>


struct arrayQueue
{
    int * pBase;
    int arrayLen;
    int queueLen;
    int front;
    int rear;
};


void arrayQueueCreat(struct arrayQueue * qQ,int lengh);
int arrayQueueIsFull(struct arrayQueue * qQ);
int arrayQueueIsEmpty(struct arrayQueue * qQ);
int enArrayQueue(struct arrayQueue * qQ,int val);
int outArrayQueue(struct arrayQueue * qQ,int * pVal);
void traverseArrayQueue(struct arrayQueue * qQ);




#endif

队列相关约定:

1. 出队只能从对头出,入队只能从队尾入。

2. 对头一般用front的值表示,它表示队列的第一个有效元素,rear表示队尾的下一个元素。

3. 如果队列长度有限,最好用静态数组实现队列,如果队列长度长且不定,最好用动态链表实现。

4. 如果用普通数组实现队列,由于数组长度是固定的,因此必须是循环队列,因为出队front的值必须加一,入队rear的值也必须加一,如果队列不循环,数组的元素长度又是固定的,那么随着不断的出队和入队,就会导致数组的很多元素不属于队列或也造成数组访问越界。

5. 循环队列核心两个参数,一个front,一个rear。两个参数不同场合不同含义:

(1)队列的初始化

        front和rear的值都为0

(2)队列非空

        front代表队列的第一个元素,rear代表队列最后一个有效元素的下一个元素

(3)队列空

        front和rear的值相等,但是不一定为0

 6. 入队伪算法

        (1)将值存入rear所代表的位置

        (2)并且让rear = (rear+1) % (数组的长度),这样做的目的是当rear到达数组的最后一个元素时,再次插入一个元素,rear的值能等于数组第一个元素的下标即0,实现循环。

         注意(n-1) % n = n-1。

9. 出队伪算法

        front = (front+1) % (数组的长度)

10. 如何判断循环队列是否为空

        如果front与rear的值相等,则该队列就一定为空。(前提是长度为n的数组,队列长度为n-1)

11. 如何判断循环队列是否为满

        (0)front与rear的值没有必要关联,front有可能比rear小,大,或相等。

        (1)当front=rear时,并且判断队列长度是否等于数组长度,如果相等,那么就代表已满。这样做的弊端是要时刻关注这个标记,不简洁。注意如果不增加这个标记那么就和如何判断队列为空矛盾了。

        (2)严格控制队列的长度为n-1,数组长度为n,这样front与rear相邻时,就认为队列为满,这样虽然会浪费一个元素,但是避免跟踪一个标记,比较灵活,常用。

 12. 队列的算法与应用

        主要是入队和出队。只要与时间相关的都可以用到队列,比如操作系统中job调度算法。有些队列是广义的队列,比如操作系统中的消息队列,往往会根据任务或job的优先级选择把job插入到队列的队尾或队头。

        如果插入到对头,那么front的值就要减减。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值