代码改变世界

算法入门之队列的链式表示

2011-10-29 17:07  java线程例子  阅读(271)  评论(0编辑  收藏  举报

          和线性类似,队列也可以有俩种存储表示。一个链队列需要都两个分别指向队头和队尾的指针(分别称为头指针和尾指针)才能唯一确定。为了操作方便,除了以上两个指针外,我们还为对列添加一个头结点。初始化是头指针和尾指针都指向头结点,因此,当头指针和尾指针均指向头结点时,此队列为空。

1. 定义存储结构:

typedef struct QNode
{
	QElemType data;		//存放的数据,称为数据域
	struct QNode *next;	//存放下一个的地址,称为指针域
} QNode, *QueuePtr;
typedef struct
{
	QueuePtr front; 		//队头指针
	QueuePtr rear;		//队尾指针
} LinkQueue;

2. 构建一个空队列Q:

Status InitQueue(LinkQueue &Q)
{

	Q.front = Q.rear = (QueuePtr) malloc(sizeof(QNode));	//向系统申请分配内存空间
	if (!Q.front)					//如果内存分配失败,程序异常退出
		exit(OVERFLOW);
	Q.front->next = NULL;		
	return OK;
}

结果如下图:

3.进队:让e进队,作为新的对尾:

Status EnQueue(LinkQueue &Q, QElemType e)
{
	QueuePtr p = (QueuePtr) malloc(sizeof(QNode)); 		//生成一个新的结点p
	if (!p)						//如果内存分配失败,如果内存分配失败,程序异常退出
		exit(OVERFLOW);
	p->data = e;					//将要进队列的值放与p的数据域data上
	p->next = NULL;					//p下一个为空
	Q.rear->next = p;					//原本的队尾rear的指针域next中存放p的地址
	Q.rear = p;					//结点p作为新的队尾
	return OK;
}

结果如下图:

再e1入队列:

4.出队:若队列不为空,则删除Q的对头元素,用x返回其值:

Status DeQueue(LinkQueue &Q, QElemType &x)
{
	if (Q.front == Q.rear)		//若队列为空,返回ERROR。
		return ERROR;
	QueuePtr p = Q.front->next;		//队头结点赋给p
	x = p->data;			//队头的数据域赋予x
	Q.front->next = p->next;		//p的指针域赋予队头的指针域
	if (Q.rear == p)			//若该队列只有一个元素,则该元素出队列后,队列为空	
		Q.rear = Q.front;
	free(p);				//释放临时结点p
	return OK;
}

结果如下图:

 

5.队头:获得队头的值,同样用x返回其值:

Status QueueHead(LinkQueue Q, QElemType &x)
{
	if(QueueEmpty(Q))
		return ERROR;
	QueuePtr p=Q.front->next;//注意这里是QueuePtr p=Q.front->next,而不是QueuePtr p=Q.front
	x=p->data;
	return OK;
}

6.判读队列是否为空:

Status QueueEmpty(LinkQueue Q)
{
	return Q.front == Q.rear;
}

7.销毁队列:

Status DestroyQueue(LinkQueue &Q){
	while(Q.front){
		Q.rear = Q.front->next;	//队尾在这里作为一个“中介”,暂时存放第二个结点
		free(Q.front);		//销毁队头
		Q.front = Q.rear;		//原先的第二个结点作为新的队头
	}
	return OK;
}

8.队列实例运用之杨辉三角如下图:

 

Status YhTriangle(LinkQueue &Q, int n){
	EnQueue(Q,1);	
	EnQueue(Q,1);
	int i = 2;	//用于控制打印数字前的缩进
	bool flag = 0;	//用于区别同一行的两个"1"
	while(n >= 2){		//前n-1行
		QElemType e;
		DeQueue(Q,e);
		if(flag && e == 1){	//若出队的是第二个"1",再进"1"。	
			flag = 0;
			EnQueue(Q,1);
			cout<<setw(4)<<e<<endl;
			--n;
		}
		else{
			if(e == 1){	//若出队的是第一个"1",再进"1"。
				for(int j = 0; j < n-i + 1; j++)
					cout<<setw(2)<<" ";
				flag = 1;
				EnQueue(Q,1);
			}
			cout<<setw(4)<<e<<" ";		
			QElemType e1 = e + Q.front->next->data;	//若出队的是一行中的第一个"1"或者非"1",使其与队头的和入队。
			EnQueue(Q,e1);
		}
	}
	while(!QueueEmpty(Q)){	//最后一行
		QElemType e2;
		DeQueue(Q,e2);
		cout<<setw(4)<<e2<<" ";
	}
	return OK;
}

图示:


注意:队头是Q.front->next;