zoukankan      html  css  js  c++  java
  • 数据结构学习--队列

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

    他的特点是:先进先出.

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


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

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

    /*************************************************************************
        > 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("当前无队列,请创建队列!
    ");
        else {
            printf("请输入入队列的元素:");
            scanf("%d", &Queue[rear + 1]);
            rear ++;
            len ++;
        }
    }
    
    void DeQueue(){
        if( !flag )  printf("当前无队列,请创建队列!
    ");
        else {
            printf("出队列的元素%d", Queue[front]);
            front ++;
            len --;
            printf("出队列后的队列为:
    ");
            for(int i = front; i <= rear; i ++)
                printf("%d", Queue[i]);
        }
    }
    
    void print(){
        printf("
    当前队列为:");
        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;
    }


  • 相关阅读:
    HTML表单元素
    hadoop编程技巧(3)---定义自己的区划类别Partitioner
    SDUTOJ 2054 双向链表
    serialVersionUID行动
    笔试
    循环队列
    css @media认识
    大约ActionContext.getContext()使用体验
    在希望的田野上--生物柴油(Biodiesel)光明的未来
    SD卡FAT32获得高速的文件格式(图文介绍)
  • 原文地址:https://www.cnblogs.com/chilumanxi/p/5136108.html
Copyright © 2011-2022 走看看