数据结构(三)之队列ADT

像栈一样,队列也是表。然而,使用队列时插入在一段进行而删除则在另一端进行。队列的基本操作是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;
}


队列主要的应用在于排队论。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值