【嵌入式学习历程10】数据结构之队列

前面 我们讲了栈,知道栈有顺序存储和链式存储两种方式,今天的主角--队列也是一样的。

我们先来理清队列的概念:

1、队列是特殊的线性表;

队列仅在线性表两端进行操作;

队头(Front):取出数据的一端;

队尾(Rear):放入数据的一端;

2、性质:先进先出(FIFO)


3、顺序队列(一般采用循环队列)

规定front指针指向队头元素,rear指针指向队尾元素的下一个位置,这样当front等于rear的时候,就表示该队列为空队列。

下面,我们上图



我们可以举个栗子,比如食堂打饭,下课之前,食堂空无一人,也就是空队列。下课后,大家陆陆续续来到食堂开始排队,但是由于空间限制,当这个队伍到一定的长度时,后面有一堵墙挡住了,就相当于队列有一个最大容量MAXSIZE,我们就假设是8,。但是我们看这个rear是如何规定的---rear指针指向队尾元素的下一个位置,所以,这个队伍实际上只能容纳7人,即对于一个容量为MAXSIZE的队列,最多只能存放MAXSIZE-1个元素。那么有人要问了,为啥不直接让rear指向最后一个元素呢,这样不就万事大吉了。然实则非也,之所以这样规定是有它的道理的。如果rear直接指向最后一个元素,那么当这个队列只有一个元素时,那么这个元素既是第一个也是最后一个,那么,front和rear就同时指向这个元素,当队列为空的时候也是front等于rear。那我们怎么区分0和1呢?

看到这里,我们就发现了顺序队列有个缺点,如果再来一个元素插进来,那么rear将何去何从呢,这时候会出现假溢出的现象,为了解决这个问题,我们一般采用循环队列。

循环队列,说白了就是头尾相接的队列,那么这种情况下,rear也会出现在front的前面。比如,上面图中的1号出队了,这时候又来个8号,这时候8号就排在了7号之后,但是rear就指向了1号出队后的空缺,那么front去哪了呢。我们为什么要取名为front呢,因为它是队头呀,那么当原本的队头1号出队了,front还有必要指向它吗?所以,当1号出队时,front已经指向了2号。我们说队列是先进先出的,那么当队列变成循环的了,应该先出那个呢?没错,这就是front的作用了,当然是先出front所指向的队头啦。


那么我们怎么知道队列的长度以及是否满了呢?

1.判断队列是否满:

(rear + 1) % MAXSIZE  = = front;

2.求取队列的长度:

(rear - front + MAXSIZE) % MAXSIZE;

注意:这里的rear和front都是数组的下标。


typedef  struct {

    int data[MAXSIZE];

    int front;

    int rear;

   }SqQueue;


初始化一个空队列Q:
   int InitQueue(SqQueue *Q)
   {
    Q->front = 0;
    Q->rear  = 0;
    return OK; 
   }

循环队列的入队列:
   int EnQueue(SqQueue *Q, int e)
   {
    if((Q->rear+1)%MAXSIZE ==Q->front)
    return ERROR;
    Q->data[Q->rear] = e;
    Q->rear=(Q->rear+1)%MAXSIZE;
      return OK;
   }

循环队列的出队列:
   int DeQueue(SqQueue *Q, int *e)
   {
    if(Q->rear==Q->front)
    return ERROR;
    *e=Q->data[Q->front];
    Q->front=(Q->front+1)%MAXSIZE;
    return OK;
   }

4、链队

队列的链式存储结构,其实就是线性表的单链表,只是它只能够从尾进队、从头出队。一般,我们将队头指针指向链队列的头结点,而将队尾指针指向尾结点。

下面我们来实现链队的基本功能

头文件:

#ifndef _LINKQUEUE_H_
#define _LINKQUEUE_H_

#define FAILURE 	10000
#define SUCCESS 	10001

typedef int ElemType;

typedef struct node
{
	ElemType data;
	struct node *next;
}Node;

typedef Node *LinkNode;

typedef struct queue
{
	LinkNode front;
	LinkNode rear;
}Queue;

typedef Queue *LinkQueue;



#endif

接口函数实现:

#include <stdio.h>
#include <stdlib.h>
#include "LinkQueue.h"

/* 初始化队列 */
int InitQueue(LinkQueue *Q)
{
	(*Q)->front = (LinkNode)malloc(sizeof(Node));
	if ((*Q) == NULL)
	{
		return FAILURE;
	}
	(*Q)->rear = (*Q)->front;
	(*Q)->front->next = NULL;
	return SUCCESS;
}

/* 进队 */
int EnQueue(LinkQueue *Q, ElemType x)
{
	LinkNode p = (LinkNode)malloc(sizeof(Node));

	if(NULL == p)
	{
		return FAILURE;
	}
	p->data = x;
	p->next = NULL;
	(*Q)->rear->next = p;
	(*Q)->rear = p;
	return SUCCESS;
}

/* 求队列长度 */
int QueueLength(LinkQueue Q)
{
	int length = 0;
	LinkNode q = Q->front;
	while(q->next)
	{
		length++;
		q = q->next;
	}
	return length;
}

/* 出队 */
int DelQueue(LinkQueue *Q)
{
	ElemType x;
	LinkNode p = (*Q)->front->next;

	if (NULL == p)
	{
		return FAILURE;
	}

	x = p->data;
	(*Q)->front->next = p->next;
	free(p);

	if (NULL == p->next)
	{
		(*Q)->rear = (*Q)->front;
	}

	return x;
}

/* 获取队头 */
int GetFront(LinkQueue *Q)
{
	LinkNode p = (*Q)->front->next;

	if (NULL == p)
	{
		return FAILURE;
	}
	return p->data; 
}

/* 清空队列 */
int ClearQueue(LinkQueue *Q)
{
	LinkNode p = (*Q)->front->next;

	if(NULL == p)
	{
		return FAILURE;
	}

	while(p)
	{
		(*Q)->front->next = p->next;
		free(p);
		p = (*Q)->front->next;
	}

	if(NULL == p)
	{
		(*Q)->rear = (*Q)->front;	
	}
	return SUCCESS;
}

/* 销毁队列 */
int DestroyQueue(LinkQueue *Q)
{
	if(NULL == (*Q))
	{
		return FAILURE;
	}

	free((*Q)->front);
	(*Q)->front = NULL;
	(*Q)->rear = NULL;
	return SUCCESS;
}

主函数:

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

int main()
{
	int ret, i;
	LinkQueue q;
	ElemType e;

	ret = InitQueue(&q);
	if (FAILURE == ret)
	{
		printf("Init Failure!\n");
	}
	else
	{
		printf("Init Success!\n");
	}

	for(i = 0; i < 10; i++)
	{
		e = i;
		ret = EnQueue(&q, e);

		if (FAILURE == ret)
		{
			printf("Enter Element Failure!\n");
		}
		else
		{
			printf("Enter %d Success!\n",e);
		}

	}

	printf("Length is %d\n", QueueLength(q));


	for(i = 0; i < 7; i++)
	{
		ret = DelQueue(&q);

		if (FAILURE == ret)
		{
			printf("Delete Element Failure!\n");
		}
		else
		{
			printf("Delete %d Success!\n",ret);
		}
	}

	printf("Length is %d\n", QueueLength(q));

	printf("Front is %d\n", GetFront(&q));
	
	ret = ClearQueue(&q);

	if (FAILURE == ret)
	{
		printf("Clear Failure!\n");
	}
	else
	{
		printf("Clear Success!\n");
	}
	printf("Length is %d\n", QueueLength(q));

	ret = DestroyQueue(&q);

	if (FAILURE == ret)
	{
		printf("Destroy Failure!\n");
	}
	else
	{
		printf("Destroy Success!\n");
	}

	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值