数据结构(三)之队列ADT

来源:互联网 发布:js获取unicode编码 编辑:程序博客网 时间:2024/05/29 15:38
像栈一样,队列也是表。然而,使用队列时插入在一段进行而删除则在另一端进行。队列的基本操作是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]);elseprintf("%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]);elseprintf("%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;}


队列主要的应用在于排队论。
0 0