队列存储及相关操作
队列和堆栈一样,也是一种具有操作约束的线性表,只允许在一端插入而在另一端删除
- 顺序存储
循环队列,为防止队列为空和队列已满不好区分,只需允许队列存放n-1个数,front指针指向第一个元素的前一个位置,尾指针指向最后一个元素
struct QNode
{
ElementType Data[MAXSIZE]; /* 存储元素的数组 */
int front; /* 队列的头指针 */
int rear; /* 队列的尾指针 */
};
typedef struct QNode *Queue;
建队
Queue CreateQueue( )
{
Queue Q = (Queue)malloc(sizeof(struct QNode));
Q->Front = Q->Rear = 0; //front和rear相等时为空
return Q;
}
入队和判断队列是否已满
void Add( Queue Q, ElementType X )
{
if ( IsFull(Q) ) printf("队列满");
else
{
Q->Rear = (Q->Rear+1)%MaxSize;
Q->Data[Q->Rear] = X;
}
}
bool IsFull( Queue Q )
{
return ((Q->Rear+1)%MaxSize == Q->Front);
}
出队和判断队列是否为空
ElementType Delete( Queue Q )
{
if ( IsEmpty(Q) )
{
printf("队列为空");
return ERROR; /* ERROR是ElementType的特殊值,标志错误 */
}
else
{
Q->Front =(Q->Front+1)%MaxSize; //注意是+而非-
return Q->Data[Q->Front];
}
}
bool IsEmpty( Queue Q )
{
return (Q->Front == Q->Rear);
}
- 链式存储
队列的链式存储结构也可以用一个单链表来表示,叫做链队,插入和删除操作分别在链表的两头进行;其中front只能是链表的头结点这一头,否则删除操作的时候,找不到前一个结点。与线性表和堆栈不同的是,要定义一个特殊的结构体存储头、尾指针,这个可以看作一个特殊的头结点
struct Node
{
ElementType Data;
struct Node *Next;
};
struct QNode
{
struct Node *Front; /* 队列的头指针 */
struct Node *rear; /* 队列的尾指针 */
};
typedef struct QNode *Queue;
建队
Queue CreateQueue( )
{ /* 构建一个队列的头、尾指针结构体,返回该结构体指针 */
Queue Q;
Q = (Queue)malloc(sizeof(struct QNode));
Q->Front=Q->rear=NULL;
return Q;
}
入队
void Add( Queue PtrQ, ElementType X )
{
Struct Node *Q;
Q = (struct Node*)malloc(sizeof(struct Node));
Q->Data = X;
Q->Next = NULL;
PtrQ->rear->Next = Q;
PtrQ->rear=Q;
}
出队和判断队列是否为空
ElementType Delete( Queue PtrQ )
{
Struct Node *Q;
ElementType X;
if ( IsEmpty(PtrQ) )
{
printf("队列空");
return ERROR;
}
else
{
Q = PtrQ->Front; //即Q指向第一个结点
if ( PtrQ->Front == PtrQ->Rear ) /* 即队列只有一个元素 */
PtrQ->Front = PtrQ->Rear = NULL; /* 删除后队列置为空 */
else
PtrQ->Front = Q->Next;
X = Q->Data;
free( Q); /* 释放被删除结点空间 */
return X;
}
}
bool IsEmpty( Queue Q )
{
return ( Q->Front == NULL);
}
队列应用
舞伴配对问题
周末舞会上,男士们和女士们进入舞厅时,各自排成一队,跳舞开始时,先入队的男士和女士先出队配成舞伴。考虑设置两个队列分别存放男士和女士入队者,先将男士和女士的记录存放在一个数组里作为输入,然后依次扫描该数组的各元素,依据性别来决定进入男队还是女队,构造完成后将队头元素配队,直到某个队列为空,然后输入非空队列的队头元素。,此人即是下一轮首先获得舞伴的人
算法步骤
①初始化两个队列 Mdancers 和 Fdancers
②反复循环,依次将跳舞者根据性别插入两个队列中
③当 Mdancers 和 Fdancers队列均为非空时,反复循环,依次输出男女舞伴的名字
④如果 Mdancers队列为空,而 Fdancers不为空,则输出 Fdancers的队头女士的名字
⑤如果 Fdancers 队列为空,而 Mdancers不为空,则输出 Mdancers的队头男士的名字
typedef struct{
char name[20]; /*构造舞者*/
char sex;
}Person;
#define MAXSIZE 100
typedef struct{
Person person[MAXSIZE];
int front; /*构造队列*/
int rear;
}Queue;
Queue Mdancers,Fdancers /*分别存放男士和女士队列*/
void DancePartner( Person dancers[], int num )
{/*结构数组dancers中存放跳舞的男女,num是跳舞的人数*/
InitQueue(Mdancers); InitQueue(Fdancers);
for(int i=0;i<num;i++)
{
Person p=dancers[i];
if(p.sex=='F') EnQueue(Fdancers,p); /*按性别入队*/
else EnQueue(Mdancers,p);
}
printf("The dancing partners are :\n");
while(!IsEmpty(Mdancers)&&!IsEmpty(Fdancers));
{
Person p = DeQueue(Mdancers);
printf("%s ",p.name);
Person p = DeQueue(Fdancers); /*队头舞者配对*/
printf("%s\n",p.name);
}
if(!IsEmpty(Mdancers))
{
Person p = GetHeadQueue(Mdancers); /*取男士队头*/
printf("The first man to get a partner is %s \n",p.name);
}
else if(!IsEmpty(Fdancers))
{
Person p = GetHeadQueue(Fdancers); /*取女士队头*/
printf("The first woman to get a partner is %s \n",p.name);
}
}