数据结构(三)--队列

队列

1.队列的定义

同栈一样,队列也是一种特殊的线性表。其主要特征为先进先出(FIFO)。常见的操作包括:

  1. 初始化
  2. 销毁
  3. 清空
  4. 判空
  5. 入队
  6. 出队
  7. 遍历

2. 队的实现

由于堆也是线性表的子集,所以队列的实现也可以分为两种:顺序队列(本文中用的是循环队列)和链队。

在具体实现前,先贴上文章代码中公有的头文件,主要是定义了一些状态宏。

//
// Created by 张兴锐 on 2018/7/25.
//

#ifndef DATASTRUCTURE_PUBLIC_H
#define DATASTRUCTURE_PUBLIC_H

// 函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASLIBLE -1
#define OVERFLOW

typedef int Status;
typedef int ElemType;

#endif //DATASTRUCTURE_PUBLIC_H

现在,先介绍一链。

3. 链队列

链队的结构如下图:

这里写图片描述

链队有两个指针,一个头指针,其next指向头结点,另一个尾指针队尾结点。

3.1 定义

//----------------链队列定义------------
/**
 * 节点
 */
typedef struct Node{
    ElemType data;
    struct Node *next;
}*LkNode;
/**
 * 队列:
 *     head 头指针
 *     tail 尾指针
 */
typedef struct LQ{
    LkNode head;
    LkNode tail;
}LinkQueue;

3.2 初始化

/**
 * 初始化队列
 * @param queue
 * @return OK
 *          ERROR
 */
Status initQueue(SqQueue &queue){
    queue.elem = (ElemType *)malloc(MAX_SIZE*sizeof(ElemType));
    if(!queue.elem) exit(ERROR);
    queue.head = 0;
    queue.tail = 0;
    return OK;
}

3.3 入队

/**
 * 入队
 * @param queue
 * @return OK
 *          ERROR
 */
Status enQueue(LinkQueue &queue,ElemType e){
    LkNode p = (LkNode)malloc(sizeof(Node));
    if(!p) exit(ERROR);
    p->data = e;
    p->next = NULL;//p->next = queue.tail->next;
    queue.tail->next = p;
    queue.tail = p;
    return OK;
}

3.4 出队

/**
 * 出队
 * @param q
 * @param e
 * @return
 */
Status deQueue(LinkQueue &queue,ElemType &e){
    if(queue.head == queue.tail) exit(ERROR);
    LkNode p = queue.head->next;
    e = p->data;
    queue.head->next = p->next;
    if(p == queue.tail) queue.tail = queue.head;        //删除最后一个元素后,tail指针丢失地址
    free(p);
    return OK;
}

需要特别注意的是,在出队操作中,

if(p == queue.tail) queue.tail = queue.head; //删除最后一个元素后,tail指针丢失地址

需要将尾指针重定向。

3.5 其余操作

/**
 * 判空
 * @param q
 * @return
 */
Status isEmpty(LinkQueue &q){
    if(q.head == q.tail) return TRUE;
    return FALSE;
}
/**
 *   销毁队列
 * @param queue
 * @return
 */
Status destroyQueue(LinkQueue &queue){
    while(queue.head){
        LkNode p = queue.head->next;
        free(queue.head);
        queue.head = p->next;
    }
    return OK;
}

4. 循环队列

由于普通循环队列中,可能存在如下情况

这里写图片描述
这时,不可继续插入新的队尾元素,又不宜开辟新的空间,毕竟原空间并没有占满。所以使用循环队列的结构。其核心在于

4.1 定义

//----------------循环队列定义------------
#define MAX_SIZE 6
typedef struct{
    ElemType *elem;
    int head;
    int tail;
}SqQueue;

4.2 初始化

/**
 * 初始化队列
 * @param queue
 * @return OK
 *          ERROR
 */
Status initQueue(SqQueue &queue){
    queue.elem = (ElemType *)malloc(MAX_SIZE*sizeof(ElemType));
    if(!queue.elem) exit(ERROR);
    queue.head = 0;
    queue.tail = 0;
    return OK;
}

4.3 入队

/**
 * 入队列
 * @param queue
 * @param e
 * @return
 */
Status enQueue(SqQueue &queue, ElemType e){
    if(queue.tail + 1 % MAX_SIZE == queue.head) exit(ERROR);
    queue.elem[queue.tail] = e;
    queue.tail = (queue.tail + 1) % MAX_SIZE;
    return OK;
}

4.4 出队

/**
 * 出队
 * @param queue
 * @param e
 * @return
 */
Status deQueue(SqQueue &queue,ElemType &e){
    if(queue.head == queue.tail) exit(ERROR);
    e = queue.elem[queue.head];
    queue.head = (queue.head+1) % MAX_SIZE;
    return OK;
}

猜你喜欢

转载自blog.csdn.net/qq_35109096/article/details/81228354