数据结构-队列 queue

队列

队列的基本概念

  1. 队列是有限个同类型元素的线性序列
  2. 队列也是一种运算受限的线性表,而且是先进先出的线性表 FIFO
  3. 新加入的数据元素加入在队尾,出队列的数据元素在队列首部被删除

如下图所示


屏幕快照 2019-04-24 16.49.55.png

队列的基本运算

  1. 队列初始化
  2. 队列判空
  3. 入队
  4. 出队
  5. 取队列首元素
  6. 清空队列
  7. 销毁队列
  8. 获取队列长度

队列的两种存储结构

顺序存储

先看一个图:


屏幕快照 2019-04-24 17.24.59.png

从上图看出,随着队列的入队、出队进行,会使整体队列向上移动(也就是向后移动),当队尾指针指向最上端的存储区域时,就不能入队了,再入队会出现溢出,但是实际上队列中还有空余空间;这种现象称为"假溢出"。
解决假溢出的方法:

  1. 方法一:每次队列出队时,让队列整体向前移动一个位置,这样就保证了队首元素始终在最前边(存储空间的首个元素地址);但是这样每次都需移动N个元素,平均时间复杂度为O(n);效率低
  2. 方法二:当队尾出现溢出时,可判断头指针位置,如果前边有空余位置,则把当前队列整体前移,这样可减少元素的移动次数,可以看做是方法一的优化;
  3. 方法三:引入循环队列的概念。可以将队列看成首尾相接的循环结构,当队尾指针到队尾后,再从头指针开始;这种方法就不需要移动元素了,这种顺序队列称为循环队列。
循环队列

当使用了循环队列,入队的队尾指针加1操作及出队的队首指针加1操作要做响应的修改,当front==rear时,有可能是空队列,也有可能队列已满,为了区分开,队列最多可容纳maxsize-1个元素。

循环队列 C语言实现

const int maxsize = 10;

typedef struct queue {
    int front;
    int rear;
    int data[maxsize];//数据为int类型
}CycleQueue;

1、队列初始化

CycleQueue *initCycleQueue() {
    CycleQueue *queue = (CycleQueue *)malloc(sizeof(CycleQueue));
    queue->front = 0;
    queue->rear = 0;
    return queue;
}

2、 队列判空

int emptyQueue(CycleQueue *queue) {
    if (queue->front == queue->rear) {
        return 1;
    }
    return 0;
}

3、入队

int enQueue(CycleQueue *queue,int x) {
    if ((queue->rear+1) % maxsize == queue->front) {
        printf("队列已满");
        return 0;
    } else {
        queue->rear = (queue->rear+1) % maxsize;
        queue->data[queue->rear] = x;
        return 1;
    }
}

4、出队

int outQueue(CycleQueue *queue) {
    if (emptyQueue(queue)) {
        printf("队列为空");
        return 0;
    } else {
        queue->front = (queue->front+1) % maxsize;
        return 1;
    }
}

5、取队列首元素

int getFirst(CycleQueue *queue) {
    if (emptyQueue(queue)) {
        printf("队列为空");
        return -1;
    } else {
        return queue->data[queue->front+1];
    }
}

6、清空队列

void clearQueue(CycleQueue *queue) {
    queue->front = 0;
    queue->rear = 0;
}

7、销毁队列

void destoryQueue(CycleQueue *queue) {
    free(queue);
    queue = NULL;
}

8、获取队列长度

int lengthQueue(CycleQueue *queue) {
    return (queue->rear-queue->front+maxsize) % maxsize;
}
链队列

1、初始化

LinkQueue *initLinkQueue(void) {
    LinkQueue *queue = (LinkQueue *)malloc(sizeof(LinkQueue));
    LinkQueueNode *node = (LinkQueueNode *)malloc(sizeof(LinkQueueNode));
    node->next = NULL;
    queue->front = node;//队列头指针指向头结点
    queue->rear = node;//队列尾指针指向尾结点
    return queue;
}

2、判空

int emptyLinkQueue(LinkQueue *queue) {
    if (queue->front == queue->rear) {
        return 1;
    }
    return 0;
}

3、入队

void enLinkQueue(LinkQueue *queue,int x) {
    LinkQueueNode *node = (LinkQueueNode *)malloc(sizeof(LinkQueueNode));
    node->data = x;
    node->next = NULL;
    queue->rear->next = node;//上个尾结点的下一结点为新加入的结点
    queue->rear = node;//重新指向尾结点
}

4、出队

void outLinkQueue(LinkQueue *queue) {
    if (emptyLinkQueue(queue)) {
        printf("队列为空");
    } else {
        LinkQueueNode *node = queue->front->next;
        queue->front->next = node->next;
        if (node->next == NULL) {
            queue->rear = queue->front;//无首结点,首尾指向头结点
        }
        free(node);
    }
}

5、获取首元素

int getFirstLinkQueue(LinkQueue *queue) {
    if (emptyLinkQueue(queue)) {
        printf("队列为空");
        return -1;
    } else {
        LinkQueueNode *node = queue->front->next;
        return node->data;
    }
}

6、获取队列长度:可添加一个变量 count,这样就不用每次都遍历一遍

int lengthLinkQueue(LinkQueue *queue) {
    int k = 0;
    if (emptyLinkQueue(queue)) {
        return k;
    }
    LinkQueueNode *node = queue->front->next;
    while (node != NULL) {
        k++;
        node = node->next;
    }
    return k;
}

7、清空队列

void clearLinkQueue(LinkQueue *queue) {
    if (!emptyLinkQueue(queue)) {
        LinkQueueNode *p,*q;
        p = queue->front->next;
        queue->front->next = NULL;//头结点指向null
    
        while (p) {//销毁结点
            q = p->next;
            free(p);
            p = q;
        }
        queue->rear = queue->front;//都指向头结点
    }
}

8、销毁队列

void destoryLinkQueue(LinkQueue *queue) {
    while (queue->front) {//销毁内部结点
        queue->rear = queue->front->next;
        free(queue->front);
        queue->front = queue->rear;
    }
}

顺序队列与链队列的优缺点

  1. 顺序队列需要预留出空间,而链队列不需要
  2. 链队列没有容量限制
  3. 链队列 除了销毁和清空队列时间复杂度为O(n),其余均为O(1)
  4. 顺序队列所有操作时间复杂度均为O(1)
  5. 顺序队列存在假溢出现象,需要使用环形队列来避免
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 我们在使用手机的时候,偶尔都会碰到过卡住的时候,比如一个地方怎么点都没有用,屏幕也卡住不显示其他东西,但当你把卡住...
    Originalee阅读 730评论 0 10
  • 代码GitHub地址 队列 队列和栈一样是特殊的线性表。区别只是它能尾进头出而已 学习队列需要清楚的认识到fron...
    HikariCP阅读 436评论 0 0
  • 一.队列的定义 队列是指在表的一端进行插入操作,在另一端进行删除操作的一种数据结构。它是一种先进先出的线性表,就如...
    yzbkaka阅读 477评论 0 1
  • 一、队列概念 队列时一种特殊的线性表,只允许在表的前端进行删除操作,而在表的后端进行插入操作,队列具有先进先出的特...
    翼动晴空阅读 994评论 0 0
  • 定义 队列(Queue):是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。 队列是一种先进先出的线性表...
    JsCoderr阅读 324评论 0 0