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

数据结构(三)之队列ADT

2014-05-02 16:10 429 查看
像栈一样,队列也是表。然而,使用队列时插入在一段进行而删除则在另一端进行。队列的基本操作是Enqueue(入队),它是在表的末端(叫做队尾(rear))插入一个元素,还有Dequeue(出队),它是删除(或返回)在表的开头(叫做队头(front))的元素。通过数组和链表都可以实现队列,其中数组更普遍一点。

在考虑数组实现时,由于数组的大小是有限的,为了操作更多的元素,我们可以用循环数组实现,即只要Front或Rear到达数组的尾端,它又绕回到开头。在考虑队列的循环实现,有两件事情要警惕,一是检测队列是否为空很重要的,因为空时一次Dequeue操作返回一个不确定的值。二是某些程序设计人员使用不同的方法来表示队列和队尾。目前比较普遍的有三种方法:

其一是使用一个计数器记录队列中元素的总数(实际上是队列长度)。

其二是少用一个元素的空间,约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空);

其三是另设一个布尔变量以匹别队列的空和满;

本文主要介绍前面两种方法。第三种比较简单,读者可自行实现。

1. 循环数组实现。添加一个计数器记录队列中元素的总数
#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct QueueRecord *Queue;

Queue createQueue(int MaxElements);
void disposeQueue(Queue Q);
void enqueue(ElementType X, Queue Q);
ElementType dequeue(Queue Q);

struct QueueRecord
{
int Capacity;
int Size;
int Front;
int Rear;
ElementType *Array;
};

Queue createQueue(int MaxElements)
{
Queue Q;

Q = (Queue)malloc(sizeof(QueueRecord));
if(Q == NULL)
return NULL;

Q->Array = (ElementType *)malloc(MaxElements * sizeof(ElementType));
if(Q->Array == NULL)
return NULL;

Q->Capacity = MaxElements;
Q->Size = 0;
Q->Front = 0;
Q->Rear = -1;

return Q;
}

void disposeQueue(Queue Q)
{
if(Q != NULL)
{
free(Q->Array);
free(Q);
}
return;
}

void enqueue(ElementType X, Queue Q)
{
if(Q->Size >= Q->Capacity)	    //队列已满
return;

if(++Q->Rear == Q->Capacity)	//假溢出
Q->Rear = 0;
Q->Size++;
Q->Array[Q->Rear] = X;

return;
}

ElementType dequeue(Queue Q)
{
if(Q->Size == 0)
return 0;

Q->Size--;
int tmp = Q->Front;
Q->Front = (Q->Front + 1) % Q->Capacity;

return Q->Array[tmp];
}

//循环打印
void printQueue(Queue Q)
{
int Rear;

if(Q == NULL || Q->Size == 0)
return;

Rear = Q->Rear;
if(Q->Front > Rear)
Rear += Q->Capacity;
for(int i = Q->Front;i <= Rear; ++i)
{
if(i >= Q->Capacity)
printf("%d", Q->Array[i - Q->Capacity]);
else
printf("%d", Q->Array[i]);
}
printf("\n");
return;
}

int main()
{
Queue Q;

Q = createQueue(10);
if(Q == NULL)
return 0;

enqueue(9, Q);
printf("%d\n", dequeue(Q));

for(int i=0; i<10; ++i)
{
enqueue(i, Q);
}
printQueue(Q);

printf("%d\n", dequeue(Q));
printQueue(Q);

enqueue(9, Q);
enqueue(9, Q);
printQueue(Q);

disposeQueue(Q);

system("pause");
return 0;
}


2.  循环数组实现。少用一个元素的空间,约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空)
#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct QueueRecord *Queue;

Queue createQueue(int MaxElements);
void disposeQueue(Queue Q);
void enqueue(ElementType X, Queue Q);
ElementType dequeue(Queue Q);

struct QueueRecord
{
int Capacity;
int Front;
int Rear;
ElementType *Array;
};

Queue createQueue(int MaxElements)
{
Queue Q;

Q = (Queue)malloc(sizeof(QueueRecord));
if(Q == NULL)
return NULL;

Q->Array = (ElementType *)malloc(MaxElements * sizeof(ElementType));
if(Q->Array == NULL)
return NULL;

Q->Capacity = MaxElements;
Q->Front = 0;
Q->Rear = 0;

return Q;
}

void disposeQueue(Queue Q)
{
if(Q != NULL)
{
free(Q->Array);
free(Q);
}
return;
}

void enqueue(ElementType X, Queue Q)
{
int rear;

rear = (Q->Rear+1) % Q->Capacity;
if(rear == Q->Front)
return;
Q->Array[Q->Rear] = X;
Q->Rear = rear;

return;
}

ElementType dequeue(Queue Q)
{
if(Q->Front == Q->Rear)
return 0;

int tmp = Q->Front;
Q->Front = (Q->Front + 1) % Q->Capacity;
return Q->Array[tmp];
}

void printQueue(Queue Q)
{
int Rear;

if(Q == NULL || Q->Front == Q->Rear)
return;

Rear = Q->Rear;
if(Q->Front > Rear)
Rear += Q->Capacity;
for(int i = Q->Front;i < Rear; ++i)
{
if(i >= Q->Capacity)
printf("%d", Q->Array[i - Q->Capacity]);
else
printf("%d", Q->Array[i]);
}
printf("\n");
return;
}

int main()
{
Queue Q;

Q = createQueue(10);
if(Q == NULL)
return 0;

enqueue(9, Q);
printf("%d\n", dequeue(Q));

for(int i=0; i<10; ++i)
{
enqueue(i, Q);
}
printQueue(Q);

printf("%d\n", dequeue(Q));
printQueue(Q);

enqueue(9, Q);
enqueue(9, Q);
printQueue(Q);

disposeQueue(Q);

system("pause");
return 0;
}


3. 单链表实现。
#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct Node *PtrToNode;
typedef struct QueueRecord *Queue;

Queue createQueue();
void disposeQueue(Queue Q);
void enqueue(ElementType X, Queue Q);
ElementType dequeue(Queue Q);

struct QueueRecord
{
PtrToNode Front;
PtrToNode Rear;
};

struct Node
{
ElementType Element;
PtrToNode Next;
};

Queue createQueue()
{
PtrToNode head;

head = (PtrToNode)malloc(sizeof(struct Node));
if(head == NULL)
return NULL;

head->Next = NULL;

Queue q;
q = (Queue)malloc(sizeof(struct QueueRecord));
if(q == NULL)
return NULL;

q->Front = head;
q->Rear = head;

return q;
}

void disposeQueue(Queue Q)
{
PtrToNode p;
PtrToNode tmp;

if(Q == NULL || Q->Front == NULL)
return;

p = Q->Front->Next;
free(Q->Front);
free(Q);
while(p != NULL)
{
tmp = p;
p = p->Next;
free(tmp);
}
return;
}

void enqueue(ElementType X, Queue Q)
{
PtrToNode tmp;

tmp = (PtrToNode)malloc(sizeof(struct Node));
if(tmp == NULL)
return;

tmp->Element = X;
tmp->Next = NULL;

Q->Rear->Next = tmp;
Q->Rear = tmp;
return;
}

ElementType dequeue(Queue Q)
{
PtrToNode tmp;

if(Q == NULL || Q->Front == NULL || Q->Front->Next == NULL)
return 0;
tmp = Q->Front->Next;
Q->Front->Next = tmp->Next;
if(tmp == Q->Rear)
Q->Rear = Q->Front;
ElementType x = tmp->Element;
free(tmp);

return x;
}

void printQueue(Queue Q)
{
PtrToNode p;

if(Q == NULL || Q->Front == NULL || Q->Front->Next == NULL)
return;

p = Q->Front->Next;
while(p != NULL)
{
printf("%d", p->Element);
p = p->Next;
}
printf("\n");

return;
}

int main()
{
Queue Q;

Q = createQueue();
if(Q == NULL)
return 0;

enqueue(1, Q);
printf("%d\n", dequeue(Q));
printf("%d\n", dequeue(Q));

for(int i =0; i < 10; ++i)
enqueue(i, Q);
printQueue(Q);

printf("%d\n", dequeue(Q));
printQueue(Q);

enqueue(9, Q);
printQueue(Q);

disposeQueue(Q);

system("pause");

return 0;
}


队列主要的应用在于排队论。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 队列