队列

队列是从现实的“排队”现象中抽象出来的:新来的只能排在队伍的最后面,当你完成的自己事情,就可以离开队列,不能插队。队列是一种特殊的线性结构,它只能在这个结构的一端插入元素,在另一端删除元素。这两端分别称为队首和队尾。

当我们一看到要频繁的插入、删除元素,第一反应就是中链表实现。的确,在原有链表的基础上,稍作改动,就能把它变成一个队列。但是,程序员们想出了一个更加巧妙地办法,利用数组,准确的说,是循环数组,来方便而快速的实现队列。

循环数组的原理其实也并不复杂,举一个例子就明白了:假设我们有a0,a1,a2,a3这4个元素组成循环数组,并有front和rear两个标记指向队列的队首和队尾。当我们将0~2这3个元素依次入队后,有:a0 = 0,a1 =1,a2 =2。且front指向a0,rear指向a3。当我们让a0出队时,并不像以前那样,通过左移a0后面的元素拉完成,而是让front指向a1,当我们在让一个3入队时,a3=3,rear指向a0.如果再让a1出队,则front指向a2,如果让5入队,则a0 = 5;rear指向a2。

概括的说,所谓的循环队列,完全是概念上YY出来的,我们还是用一般的数组来实现的,但是通过front和rear两个标记,是得队列按照我们事先设定的顺序排列出来。每当给队尾增加一个元素时,rear+1;但是如果rear已经指向数组的最后一个位置,那么通过取模的办法,可以让他跳转到第一个位置(如果这个位置不被队首元素占据的话)。每次出队时,front+1,同样的,如果front已经到了数组的最后,可以通过取模的办法让他跳转到数组的第一个。

下面我们具体看程序:

typedef int ElemType;

typedef struct Queue
{
	ElemType* data;
	int front;
	int rear;
	int Qsize;

}Queue;

//初始化通过参数传进来创建队列的大小
bool initQueue(Queue* q,int size)
{
	q->front = 0;
	q->rear = 0;
	q->Qsize = size;
	q->data = (ElemType*)malloc(q->Qsize*sizeof(ElemType));
	if( NULL == q->data)
		return false;
	return true;

}

//销毁队列,释放内存
void destroyQueue(Queue* q)
{
	q->front = 0;
	q->rear = 0;
	q->Qsize = 0 ;
	free((q->data));
	q->data = NULL;
}

//清空队列
void clearQueue(Queue* q)
{
	q->front = 0;
	q->rear = 0;
}

//判断队列是否为空
bool is_empty(Queue *q)
{
	if(q->front == q->rear)
	{
		printf("the queue is empty! \n");
		return true;
	}
	else
	{
		return false;	
	}
}

//返回队首元素
bool getHead(Queue *q,ElemType *e)
{
	if(is_empty(q))
	{
		printf("can not get the head element! \n");
		return false;
	}
	else
	{
		*e = q->data[q->front];
		return true;
	}
}

//返回队列长度:在循环队列中
int Qlength(Queue *q)
{
	return (q->rear-q->front+q->Qsize)%q->Qsize;
}

//入队
bool enQueue(Queue *q,ElemType e)
{
	//如果队列已满,重新分配内存
	if(q->rear == q->Qsize-1)
	{
		q->data = (ElemType*)realloc(q->data,2*q->Qsize*sizeof(ElemType));
		if(q->data == NULL)
			return false;
		else
			q->Qsize *= 2;
	}
	//先赋值,然后队尾循环加1
	q->data[q->rear] = e;
	q->rear = (q->rear+1)%q->Qsize;
	return true;

}

bool deQueue(Queue *q,ElemType *e)
{
	if(is_empty(q))
		return false;
	else
	{
		*e = q->data[q->front];
		//队首标记循环加1
		q->front = (q->front+1) % q->Qsize;
	}
	return true;
}


我在定义时,专门定义了队列的容量,以防止不停的放里面加入元素时越界情况的发生。还有一点需要注意,当我定义了5个长度的队列时,实际能用的只有4个,另外一个供队尾标记使用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值