您的位置:首页 > 理论基础 > 数据结构算法

基本数据结构之队列

2013-08-24 09:36 316 查看
一、基本数据结构之队列

       队列作为计算机系统一种非常常见的数据结构被大家所熟知。同堆栈一样,队列也是有插入和删除只能在限定段的线性表。

         队列是一种FIFO(First In First Out)的线性表。具体通常用链表或数组来实现。队列只允许在后端(rear)进行插入操作,在前段(front)进行删除操作。

         队列的操作方式和堆栈类似,唯一的区别就是队列只允许在后端进行数据添加。

         队列通常能够解决一下问题:

         1)解决主机与外部设备之间速度不匹配的问题。设置一个缓冲队列。

         2)解决因多用户引起的资源竞争问题。系统按照请求时间设置一个请求队列(还可以给每个任务加一个优先级,就成为了优先级队列)。

         下面介绍队列的几种常见的实现方式:

        

/*
单链队列的实现:单链队列使用链表作为基本数据结构,所以不存在溢出问题(除非主存耗完),队列长度也没有限制。
但是插入和读取的时间成本较高。
*/
/* 单链队列--队列的链式存储结构 */
typedef struct QNode {
QElemType data;
struct QNode *next;
}QNode, *QueuePtr;

typedef struc {
QueuePtr front, rear; /* 队头队尾指针 */
}LinkQueue;

/* 链队列的基本操作(9个) */

/* 构造一个空队列 */
void InitQueue(LinkQueue *Q)
{
Q->font = Q->rear = malloc(sizeof(QNode);
if(!Q->font)
exit(1);
Q->front->next = NULL;
}

/* 销毁队列Q */
void DestroyQueue(LinkQueue *Q)
{
while(Q->front) {
Q->rear = Q->front->next;
free(Q->front);
Q->front = Q->rear;
}
}

/* 清空队列Q */
void ClearQueue(LinkQueue *Q)
{
QueuePtr p,q;
Q->rear = Q->front;
p = Q->front->next;
Q->front->next = NULL;
while(p) {
q = p;
p = q->next;
free(q);
}
}

/* 若Q为空队列,则返回TRUE,否则返回FALSE */
Status QueueEmpty(LinkQueue Q)
{
if(Q->font->next == NULL)
return TRUE;
else
return FALSE;
}

/* 求队列的长度 */
int QueueLength(LinkQueue Q)
{
int i = 0;
QueuePtr p;
p = Q.front;
while(Q.rear != p) {
i++;
p = p->next;
}
return i;
}

/* 若队列不为空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */
Status GetHead_Q(LinkQueue Q, QElemType *e)
{
QueuePtr p;
if(Q.front == Q.rear)
return ERROR;
p = Q.front->next;
*e = p->data;
return OK;
}

/* 插入e作为Q新的队尾元素 */
void EnQueue(LinkQueue *Q, QElemType e)
{
QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
if(!p)
exit(1);
p->data = e;
p->next = NULL;
Q->rear->next = p;
Q->rear = p;
}

/* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
Status DeQueue(LinkQueue *Q, QElemType *e)
{
QueuePtr p;
if(Q->front == Q->rear)
return ERROR;
p = Q->front; /* 指向头结点 */
*e = p->data;
Q->front = p->next;
if(Q->rear == p)
Q->rear = Q->front;
free(p);
return OK;
}

/* 从队头到队尾依次对队列Q中每个元素调用函数vi() */
void QueueTraverse(LinkQueue Q, (void)(*visit)(QElemType))
{
QueuePtr p;
p = Q.front->next;
while(p) {
visit(p->data);
p = p->next;
}
printf("\n");
}
-----------------------------我就是分割线啦---------------------------
循环队列
循环队列可以更简单防止伪溢出的发生,但队列大小是固定的。
/* 队列的顺序存储结构(循环队列) */
#define MAX_QSIZE 5 /* 最大队列长度加1*/
typedef struct {
QElemType *base;/* 初始化的动态分配存储空间 */
int front;/* 头指针,若队列不空,指向队列头元素 */
int rear;/* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
}SqQueue;

循环队列的基本操作(9个)
/* 构造一个空队列 */
void InitQueue(SqQueue *Q)
{
Q->base = malloc(MAX_QSIZE * sizeof(QElemType));
if(!Q->base)
exit(1);
Q->front = Q->rear = 0;
}

/* 销毁队列Q,Q不再存在 */
void DestroyQueue(SqQueue *Q)
{
if(Q->base)
free(Q->base);
Q->base = NULL;
Q->front = Q->rear = 0;
}

/* 将Q清为空队列 */
void ClearQueue(SeQueue *Q)
{
Q->front = Q->rear = 0;
}

/* 若队列Q为空队列,则返回TRUE;否则返回FALSE */
Status QueueEmpty(SqQueue Q)
{
if(Q.front == Q.rear)
return TRUE:
else
return FALSE:
}

/* 返回Q的元素个数,即队列的长度 */
int QueueLength(SeqQueue Q)
{
return (Q.rear - Q.front + MAX_QSIZE) % MAX_QSIZE;
}

/* 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR */
Status GetHead(SqQueue Q, QElemType *e)
{
if(Q.front == Q.rear)
return ERROR; // 队列为空
*e = Q.base[Q.front];
return OK;
}

/* 插入元素e为Q的新的队尾元素 */
Status EnQueue (SeQueue *Q, QElemType *e)
{
if((Q->rear+1)% MAX_QSIZE == Q->front) // 队列满
return ERROR;
Q->base[Q->rear] = e;
Q->rear = (Q->rear + 1) % MAX_QSIZE;
return OK;
}

/* 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR */
Status DeQueue(SqQueue *Q, ElemType *e)
{
if(Q->front == Q->rear) // 队列空
return ERROR;
*e = Q->base[Q->front];
Q->front = (Q->front+1) % MAX_QSIZE;
return OK;
}

/* 从队头到队尾依次对队列Q中每个元素调用函数visit() */
void QueueTraverse(SqQueue Q, void(*visit)(QElemType))
{
int i ;
i = Q.front;
while(i!=Q.rear)
{
visit(Q.base[i];
i = (i+1)%MAX_QSIZE;
}
printf("\n");
}
---------------------------------------------我还是分割线---------------------
#include<stdio.h>
#include<stdlib.h>
/*阵列结构,说白了就是用数组存储元素 */
struct Queue
{
int Array[10];//阵列空间大小
int head;//前端(front)
int tail;//后端(rear)
int length;//当前队列长度,并且使用此成员判断满和空
};

/*元素插入队列*/
void EnQueue(struct Queue *Queue1,int x)
{
Queue1->Array[Queue1->tail]=x;
if(Queue1->tail+1==10)//Queue1->length 改空间大小为10
{
Queue1->tail=0;//1改为0
}
else
{
Queue1->tail=Queue1->tail+1;
}
Queue1->length=Queue1->length+1;//当前个数增1
}

/*删除队列元素*/
int DeQueue(struct Queue *Queue1)
{
int x=Queue1->Array[Queue1->head];
if(Queue1->head+1==10)//空間大小10
{
Queue1->head=0;
}
else
{
Queue1->head=Queue1->head+1;
}
Queue1->length=Queue1->length-1;//移出后減少1
return x;
}
/*基本操作*/
int main()
{
struct Queue *Queue1=malloc(sizeof(struct Queue));
Queue1->length=0;
Queue1->head=0;
Queue1->tail=0;
EnQueue(Queue1,5);//將5放入
EnQueue(Queue1,8);//將8放入
EnQueue(Queue1,3);//將3放入
EnQueue(Queue1,2);//將2放入
printf("%d ",DeQueue(Queue1));
printf("%d ",DeQueue(Queue1));
printf("%d ",DeQueue(Queue1));
system("pause");
}

Note:以上便是队列的基本介绍,包括队列的概念以及应用,最后介绍了,队列的几种常见实现方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息