数据结构--队列

数据结构--队列

队列ADT

队列像栈一样,也是一个表。使用队列时,从一端进行插入,从另一端进行删除。队列的基本操作是入队(Enquence),它是在表的末端即队尾(rear)插入一个元素;还有出队(Dequeue),它是删除(或返回)在表的开头即队头(front)的元素。队列同样也有两种存储方法,分别是顺序循环存储结构和链式存储结构。

队列的数组实现

对于每一个队列的数据结构,我们保留一个数组Queue[ ],以及位置Front 和 Rear ,他们代表队列的两端。我们还要记录实际存在于队列的元素的个数Size。为使一个元素X入队,我们让Size 和 Rear 增加1,然后置Queue[Rear] = X。为使一个元素出队,我们置返回值为Queue[Front],Size减1,然后使Front增1。但是这种实现存在一个问题,经过多次入队后,再下一次入队就会是一个不存在的位置,然而,队列中也许只存在几个元素,因为若干元素可能已经出队了。简单的解决方法是:只要Front 和 Rear 到达数组的尾端,它就绕回开头,这种叫做循环数组实现。

1.定义顺序循环队列结构体


typedef struct 
{
	ElementType Queue[MaxQueueSize];
	int Rear;
	int Front;
	int Size;
}SequenceQueue;

2.初始化顺序循环队列

void QueueInitiate(SequenceQueue *Q)
{
	Q->Rear = 0;
	Q->Front = 0;
	Q->Size = 0;
}

3.判断队列是否为空


int QueueNotEmpty(SequenceQueue Q)
{
	if(Q.Size == 0) 
		return 0;  /*队列为空时返回0,否则返回1 */
	else
		return 1;
}

4.入队列


int EnQueue(SequenceQueue *Q, ElementType X)
{
	if(Q->Size > 0 && Q->Rear == Q->Front)
	{
		printf("Out of space");
		return 0;
	}
	else
	{
		Q->Queue[Q->Rear] = X;
		Q->Rear = (Q->Rear + 1) % MaxQueueSize;
		Q->Size ++;		
                return1;
	}
}



5.出队列


int DeQueue(SequenceQueue *Q, ElementType *X)
{
	if(Q->Size == 0)
	{
		printf("Out of space");
		return 0;
	}
	else
	{
		*X = Q->Queue[Q->Front];
		Q->Front = (Q->Front + 1) % MaxQueueSize;
		Q->Size--;
		return 1;
	}
}


6.获取队头数据元素

int QueueGet(SequenceQueue *Q, ElementType *X)
{
	if(Q->Size == 0)
	{
		printf("Out of space");
		return 0;
	}
	else
	{
		*X = Q->Queue[Q->Front];
		return 1;
	}
}

队列的链表实现

1. 链式队列的结构体

typedef struct QueueNode
{
	ElementType data;
	struct QueueNode *next;
}LinkQueueNode;

typedef struct 
{
	LinkQueueNode * Front;
	LinkQueueNode * Rear;
}LinkQueue;

2.队列初始化

void QueueInitiate(LinkQueue *Q)
{
	Q->Rear = NULL;
	Q->Front = NULL;
}


3.判断队列是否为空


int QueueNotEmpty(LinkQueue Q)
{
	if(Q->Front == NULL)
		return 0;
	else
		return 1;
}



4.入队列


int EnQueue(LinkQueue *Q, ElementType X)
{
	LinkQueueNode *p;
	if((p=(LinkQueueNode *) malloc(sizeof(LinkQueueNode))) == NULL)
	{
		printf("Out of space");
		return 0;
	}
	p->data = x;
	p->next = NULL;
	if(Q->Rear != NULL)
		Q->Rear->next = p;
	Q->Rear = p;
	if(Q->Front == NULL)
		Q->Front = p;
	return 1;
}



5.出队列

int DeQueue(LinkQueue *Q, ElementType *X)
{
	LinkQueueNode *p;
	if(Q->Front == NULL) 
	{
		printf("Out of space");
		return 0;
	}
	else
	{
		*X = Q->Front->data;
		p = Q->Front;
		Q->Front = Q->Front->next;
		if(Q->Front == NULL)
			Q->Rear = NULL;
		free(p);
		return 1;
	}
}

6.返回队头数据元素


int QueueGet(LinkQueue Q, ElementType *X)
{
	if(Q.Front == NULL)
	{
		printf("Out of space");
		return 0;
	}
	else
	{
		*X = Q.Front->data;
		return 1;
	}
}

7.取队头数据元素


void Destory(LinkQueue Q)
{
	LinkQueueNode *p, *p1;
	p = Q->Front;
	while(p != NULL)
	{
		p1 = p;
		p = p->next;
		free(p1);
	}
}

队列的应用

1.解决具有先进先出排队特点的问题

2.解决农夫过河问题
一个农夫带着一只狼,一只羊和一棵白菜,欲从河的北岸坐船到南岸去。小船只能容纳农夫和一件物品,只有农夫撑船。另外,狼会吃羊,羊会吃白菜,所以农夫不能单独地留下狼和羊自己离开,或者留下羊和白菜自己离开。
解决:
1.将农夫、狼、羊和白菜在河的北岸和南岸的情况,抽象为N种不同状态组合,而这些状态之间可以相互转变,只要找到一组运算可以将初始状态转为目标状态,那么问题就解决了。
2.使用广度优先搜索获得所有的状态,显然可以用队列的方式实现。
3.使用一个4位二进制数从左到右表示农夫、狼、白菜和羊的位置,0表示该角色在南岸,1则表示该角色在北岸。那么问题转为从初始状态0000(全部在南岸)开始,寻找一种安全状态序列1111(全部在北岸)的过程。
4.用函数location表示这个4位的二进制,用函数safe判断安全状态。
5.利用以整数队列来实现广度优先搜索,记录已被访问的各个状态以及相应的路径,构造一个整数顺序表route记录所有的状态,共16种(0000~1111)。在顺序表中每个元素初始值为-1。

3.使用队列给出提高运行效率的算法



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值