队列

422 阅读3分钟
  • 概念

    队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

  • 特点

    队尾入队,队头出队,先进先出
  • 队列的顺序存储实现

    1. 假溢出现象
      当有队列元素进队的时候rear就会加一当打到MAXSIZE的时候就会被认为队列已满已近不能继续入队,但是此时出队一个元素front加一,这时候就会多出一个存储空间,但是应为rear已经等于MAXSIZE,所以无法再入队,这时就造成了假溢出现象,针对于这种现象一般会使用循环队列来解决类似问题。
    2. 循环队列

    在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。自己真从MaxSize-1增1变到0,可用取余运算rear%MaxSize和front%MaxSize来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列

    1. 初始化
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    typedef int ElemType;
    typedef int Status;
    
    typedef struct {
        ElemType * data;
        int rear;
        int front;
        int maxSize;
    }Queue;
    
    //初始化
    Status initQueue(Queue *q,int maxSize){
        q->data = (ElemType *)malloc(sizeof(ElemType) * maxSize);
        if(q->data == NULL) exit(0);
        q->rear = 0;
        q->front = 0;
        q->maxSize = maxSize;
        return OK;
    }
    
    1. 判空、判满、获取队列长度、获取队尾元素、遍历
    //判空
    Status queueIsEmpty(Queue q){
        if(q.data == NULL) exit(0);
        if(q.rear == q.front) return TRUE;
        return FALSE;
    }
    
    //判断队列是否为满队列
    Status queueIsFull(Queue q){
        if(q.data == NULL) exit(0);
        if((q.rear + 1)%q.maxSize == q.front) return TRUE;
        return FALSE;
    }
    
    //获取队列长度
    int getLength(Queue q){
        if(q.data == NULL) exit(0);
        return (q.rear - q.front + q.maxSize)%q.maxSize;
    }
    
    //获取队尾元素
    Status getRear(Queue q, ElemType *data){
        if(q.data == NULL) exit(0);
        if(queueIsEmpty(q)) return ERROR;
        *data = q.data[q.rear-1];
        return OK;
    }
    
    //遍历
    Status traverseQueue(Queue q){
        if(q.data == NULL) exit(0);
        for(int i = q.front; i != q.rear; i = (i+1)%q.maxSize)
            printf("%d ",q.data[i]);
        printf("\n");
        return OK;
    }
    
    1. 入队
    //入队
    Status enqueue(Queue *q,ElemType data){
        if(q->data == NULL) exit(0);
        if(queueIsFull(*q)) return ERROR;
        q->data[q->rear] = data;
        q->rear = (q->rear + 1) % q->maxSize;
        return OK;
    }
    
    1. 出队
    //出队
    Status dequeue(Queue *q){
        if(q->data == NULL) exit(0);
        if(queueIsEmpty(*q)) return ERROR;
        q->front = (q->front + 1)%q->maxSize;
        return OK;
    }
    
  • 队列的链式存储实现

    1. 初始化
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    typedef int ElemType;
    typedef int Status;
    
    typedef struct QueueNode{
        ElemType data;
        struct QueueNode * next;
    }QueueNode,*QueueNodePtr;
    
    typedef struct Queue{
        QueueNodePtr front;
        QueueNodePtr rear;
    }Queue;
    
    
    
    //初始化
    Status initQueue(Queue *q){
        q->front = q->rear = (QueueNodePtr)malloc(sizeof(QueueNode));
        if(q->front == NULL) exit(0);
        q->front->next = NULL;
        return OK;
    }
    
    1. 判空、获取队尾元素、清空队列、销毁队列
    //判空
    Status queueIsEmpty(Queue q){
        if(q.front == NULL) exit(0);
        if(q.front == q.rear) return TRUE;
        return FALSE;
    }
    
    //获取队尾元素
    Status getRear(Queue q, ElemType *data){
        if(q.front == NULL) exit(0);
        if(queueIsEmpty(q)) return ERROR;
        *data = q.rear->data;
        return OK;
    }
    
    //清空队列
    Status clearQueue(Queue *q){
        if(q->front == NULL) exit(0);
        if(queueIsEmpty(*q)) return ERROR;
        q->rear = q->front->next;
        while (q->rear !=NULL) {
            q->front->next = q->rear->next;
            free(q->rear);
            q->rear = q->rear->next;
        }
        q->rear = q->front;
        return OK;
    }
    
    //销毁队列
    Status destroyQueue(Queue *q){
        if(q->front == NULL) exit(0);
        if(clearQueue(q)){
            q->front = q->rear =NULL;
            return OK;
        }
        return ERROR;
    }
    
    
    1. 入队
    //入队
    Status enqueue(Queue *q,ElemType data){
        if(q->front == NULL) exit(0);
        QueueNodePtr ptr = (QueueNodePtr)malloc(sizeof(QueueNode));
        ptr->data = data;
        ptr->next = q->front->next;
        q->front->next = ptr;
        if(q->front == q->rear){
            q->rear = ptr;
        }
        return OK;
    }
    
    1. 出队
    //出队
    Status dequeue(Queue *q){
        if(q->front == NULL) exit(0);
        if(queueIsEmpty(*q)) return ERROR;
        QueueNodePtr temp = q->rear;
        QueueNodePtr target = q->front;
        while (target->next != temp) {
            target = target->next;
        }
        target->next = NULL;
        q->rear = target;
        free(temp);
        return OK;
    }