数据结构学习--队列

队列与栈类似,也同样基于线性表.

他的特点是:先进先出.

如我们日常说的队列一样,后来的人后走,先来的人先走.下面用图片形象的展示一下:


队列有队头和队尾,队头是先进入的元素,队尾是后进入的元素

他同样有两种存储模式,分别实现一下:
链式:

/*************************************************************************
    > File Name: 队列的实现.c
    > Author: zhanghaoran
    > Mail: chilumanxi@gmail.com 
    > Created Time: 2015年07月22日 星期三 20时35分35秒
 ************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define OVERFLOW -2
#define OK 1
#define ERROR 0
//链表
//队列元素的数据
typedef struct cQueue{
	int data;
	struct cQueue *next;
}QNode, *QueuePtr;

typedef struct{
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

int InitQueue(LinkQueue &Q){
	Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
	if(Q.front == NULL)
		exit(OVERFLOW);
	Q.front -> next = NULL;
	return OK;
}

int DestroyQueue(LinkQueue &Q){
	while(Q.front != NULL){
		Q.rear = Q.front -> next;
		free(Q.front);
		Q.front = Q.rear;
	}
	return OK;
}

int EnQueue(LinkQueue &Q, int e){
	QueuePtr q;
	q = (QueuePtr)malloc(sizeof(QNode));
	q -> data = e;
	q -> next = NULL;
	Q.rear -> next = q;
	Q.rear = q;
	return OK;
}

int DeQueue(LinkQueue &Q){
	QueuePtr q;
	int e;
	if(Q.front == Q.rear)
		return ERROR;
	q = Q.front -> next;
	e = q -> data;
	Q.front -> next = q -> next;
	if(Q.rear == q)
		Q.rear = Q.front;
	free(q);
	return e;
}

int ClearQueue(LinkQueue &Q){
	QueuePtr q;
	q = Q.front;
	while(q -> next != NULL){
		Q.front = Q.front -> next;
		free(q);
		q = Q.front;
	}
	Q.rear = NULL;
	return OK;
}

int QueueEmpty(LinkQueue Q){
	if(Q.front -> next == NULL)
		return OK;
	else 
		return ERROR;
}

int GetHead(LinkQueue Q){
	if(!QueueEmpty(Q))
		return Q.front -> next -> data;
	else 
		return ERROR;
}

int main(void){
	LinkQueue Queue;
	int a[8] = {3, 8, 5, 17, 9, 30, 15, 22};
	int i;
	InitQueue(Queue);
	for(i = 0; i < 8; i ++){
		EnQueue(Queue, a[i]);
	}
	printf("%d ", DeQueue(Queue));
	printf("%d ", DeQueue(Queue));
	EnQueue(Queue, 68);
	printf("%d ", GetHead(Queue));
	printf("%d ", GetHead(Queue));
	while(!QueueEmpty(Queue)){
		printf("%d ", DeQueue(Queue));
	}
	printf(" ");
	ClearQueue(Queue);
	return 0;
}



这个的实现就是以队头作为一个头结点,入队就是尾插,出队就是删除第一个结点.

当然需要注意一点就是出队的时候如果恰好出队的是队尾元素的话,那就要让队尾元素指向头结点,否则队尾指针将会丢失.

好的,下面我们给出一个经常使用的数据结构的数组实现:

#include <stdio.h>
#include <stdlib.h>

#define OVERFLOW -2
#define OK 1
#define ERROR 0
#define INIT_QUEUE_SIZE 100

int Queue[INIT_QUEUE_SIZE];
int flag = 0;
int front = 0, rear = 0;
int len = 0;

void CreatQueue(){
    if(flag == 1)
        printf("队列已经存在。");
    else {
        for(int i = 0; i < 6; i ++){
            printf("输入初始化的第%d个数", i);
            scanf("%d", &(Queue[i]));
            len ++;
        }
        rear = 5;
        flag = 1;
    }
}

void EnQueue(){
    if( !flag )  printf("当前无队列,请创建队列!\n");
    else {
        printf("请输入入队列的元素:");
        scanf("%d", &Queue[rear + 1]);
        rear ++;
        len ++;
    }
}

void DeQueue(){
    if( !flag )  printf("当前无队列,请创建队列!\n");
    else {
        printf("出队列的元素%d", Queue[front]);
        front ++;
        len --;
        printf("出队列后的队列为:\n");
        for(int i = front; i <= rear; i ++)
            printf("%d", Queue[i]);
    }
}

void print(){
    printf("\n当前队列为:");
    for(int i = front; i < len; i ++)
        printf("%d ",Queue[i]);
}

在数组的情况下,我们只需要定义两个整型作为队尾和队头就可以了,非常的简便,在ACM以及各种算法题目中,这种形式是最长用的,比如BFS.详情使用见我的博客的另外两篇文章:http://blog.csdn.net/chilumanxi/article/details/46363361

http://blog.csdn.net/chilumanxi/article/details/46317013


当然,队列也有自己的循环队列.在初始化建空队列的时候,我们令front = rear = 0,每当插入新的队列尾元素的时候,尾指针加一.每当删除头元素的时候,头指针加一,这样一来,头指针就可以始终指向第最先入队的元素.

那么问题最后就是如果队列已满的话,尾指针的下一位置就是头指针.下面写一下循环队列:

//-----------------循环队列---队列的顺序存储结构-------
#define MAXQSIZE 100             //最大队列长度
#define Status int
typedef struct{
  QElemType *base;               //初始化的动态分配存储空间 
  int front;                     //头指针,若队列不空,指向队列头元素
  int rear;                      //尾指针,若队列不空,指向队列尾元素的下一个元素
}SqQueue;

//-----------------循环队列的基本操作的算法描述---------
Status InitQueue(SqQueue &Q){
  //构造一个空队列Q
  Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));
  if(!Q.base) exit(OVERFLOW);
  Q.front = Q.rear = 0;
  return OK;
}

int QueueLength(SqQueue Q){
  //返回Q的元素个数,也就是队列的长度
  return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE    //循环队列,所以求余
}

Status EnQueue(SqQueue &Q, QElemType e){
  //输入元素e为Q的新的队尾元素
  if((Q.rear + 1) % MAXQSIZE == Q.front)  return ERROR; //队列满
  Q.base[Q.rear] = e;
  Q.rear = (Q.rear + 1) % MAXQSIZE;
  return OK;
}

Status DeQueue(SqQueue &Q, QElemType &e){
  //若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
  if(Q.front == Q.rear)  return ERROR;
  e = Q.base[Q.front];
  Q.front = (Q.front + 1) % MAXQSIZE;
  return OK;
}


posted @ 2015-07-22 21:31  ChiLuManXi  阅读(205)  评论(0编辑  收藏  举报