顺序队列的优化

我们既然想优化顺序队列,首先得知道目前顺序队列的瓶颈在哪里,那样才能对症下药。

顺序队列的瓶颈:

1.线性表的第一个元素作为队头,线性表的最后一个元素作为队尾;
2.入队的新元素是在线性表的最后,时间复杂度为O(1)
3.出队时需要将后续的所有元素向前移动,时间复杂度O(n)
问题:如何将出队操作的时间复杂度降低到O(1)?

顺序队列的优化方案
1.定义front使其始终代表队头的下标,出队时将队头元素返回,且front++;
2.定义rear使其始终代表队尾下一个元素的下标,入队时将新元素插入,且rear++。
没有必要只将下标为0的位置定义为队头!!

队头元素: node[4]                队列长度:6

顺序队列的关键状态
1.初始状态:length == 0, front == 0, rear == 0;
2.空队列状态:length == 0, front == rear;
3.满队列状态:length == capacity, front == rear;

从关键状态我们发现,队列为空时或者满时都有front = rear,这样就不是很好判断队列的空和满的状态,但是这些都难不倒我们,我们可以通过两种方式来解决这个问题:1.另设一个标志位以区别队列的“空”还是“满”,就比如上面的length;2.少用一个元素空间,约定以“队列头指针在队列尾指针的下一位置上”作为队列呈“满”状态。满队列:front = (rear + 1) % capacity;空队列:front =rear。
循环使用队列中的空间
1.入队:rear = (rear + 1) % capacity;

2.出队:front = (front + 1) % capacity;

下面我们看一下代码

创建队列

typedef unsigned int TSeqQueueNode;
// 定义一个顺序队列结构体
typedef struct _tag_SeqQueue
{int capacity;int length;int front;int rear;TSeqQueueNode* node;
} TSeqQueue;
// 创建队列
SeqQueue* SeqQueue_Create(int capacity) // O(1)
{TSeqQueue* ret = NULL;// 队列容量合法性OK,为队列申请内存if( capacity >= 0 ){ret = (TSeqQueue*)malloc(sizeof(TSeqQueue) + sizeof(TSeqQueueNode) * capacity);}// 内存申请成功,定义空队列if( ret != NULL ){ret->capacity = capacity;ret->length = 0;ret->front = 0;ret->rear = 0;ret->node = (TSeqQueueNode*)(ret + 1);}return ret;
}

从代码中看出,创建顺序队列和创建顺序表基本相似,就是多了ret->front = 0;和ret->rear = 0。

销毁队列和清空队列:

// 销毁队列
void SeqQueue_Destroy(SeqQueue* queue) // O(1)
{free(queue);
}
// 清空队列
void SeqQueue_Clear(SeqQueue* queue) // O(1)
{TSeqQueue* sQueue = (TSeqQueue*)queue;// 队列合法性检查OKif( sQueue != NULL ){sQueue->length = 0;sQueue->front = 0;sQueue->rear = 0;}
}

还是和操作顺序表基本相似。

进队列代码

// 进队列
int SeqQueue_Append(SeqQueue* queue, void* item) // O(1)
{// 定义顺序表队列变量,强制转换入口参数TSeqQueue* sQueue = (TSeqQueue*)queue;// 入口参数合法性检查int ret = (sQueue != NULL) && (item != NULL);ret = ret && (sQueue->length + 1 <= sQueue->capacity);// 合法性检查OK,插入新元素,尾指针加1,队列长度加1if( ret ){sQueue->node[sQueue->rear] = (TSeqQueueNode)item;sQueue->rear = (sQueue->rear + 1) % sQueue->capacity;sQueue->length++;}return ret;
}

出队列代码

// 出队列
void* SeqQueue_Retrieve(SeqQueue* queue) // O(1)
{// 定义顺序表队列变量,强制转换入口参数TSeqQueue* sQueue = (TSeqQueue*)queue;// 取出队头元素void* ret = SeqQueue_Header(queue);// 取队头元素OK,头指针加1,队列长度减1if( ret != NULL ){sQueue->front = (sQueue->front + 1) % sQueue->capacity;sQueue->length--;}// 返回头元素地址return ret;
}

获取对头元素、队列长度、队列容量

// 获取队头元素
void* SeqQueue_Header(SeqQueue* queue) // O(1)
{// 定义顺序表队列变量,强制转换入口参数TSeqQueue* sQueue = (TSeqQueue*)queue;void* ret = NULL;// 队列合法性检查OK,返回队列头元素地址if( (sQueue != NULL) && (sQueue->length > 0) ){ret = (void*)(sQueue->node[sQueue->front]);}return ret;
}
// 获取队列的长度
int SeqQueue_Length(SeqQueue* queue) // O(1)
{// 定义顺序表队列变量,强制转换入口参数TSeqQueue* sQueue = (TSeqQueue*)queue;int ret = -1;// 队列合法性检查OK,返回队列长度if( sQueue != NULL ){ret = sQueue->length;}return ret;
}
// 获取队列的容量
int SeqQueue_Capacity(SeqQueue* queue) // O(1)
{// 定义顺序表队列变量,强制转换入口参数TSeqQueue* sQueue = (TSeqQueue*)queue;int ret = -1;// 队列合法性检查OK,返回队列容量if( sQueue != NULL ){ret = sQueue->capacity;}return ret;
}

测试代码

#include <stdio.h>
#include <stdlib.h>
#include "SeqQueue.h"/* run this program using the console pauser or add your own getch, system("pause") or input loop */int main(int argc, char *argv[])
{SeqQueue* queue = SeqQueue_Create(6);int a[10] = {0};int i = 0;for(i=0; i<10; i++){a[i] = i + 1;SeqQueue_Append(queue, a + i);}printf("Header: %d\n", *(int*)SeqQueue_Header(queue));printf("Length: %d\n", SeqQueue_Length(queue));printf("Capacity: %d\n", SeqQueue_Capacity(queue));while( SeqQueue_Length(queue) > 0 ){printf("Retrieve: %d\n", *(int*)SeqQueue_Retrieve(queue));}printf("\n");for(i=0; i<10; i++){a[i] = i + 1;SeqQueue_Append(queue, a + i);printf("Retrieve: %d\n", *(int*)SeqQueue_Retrieve(queue));}SeqQueue_Destroy(queue);return 0;
}

到此也就完成了顺序队列的优化,整体代码请点击下方的链接。

顺序队列的优化C实现

数据结构之顺序队列的优化相关推荐

  1. 数据结构之链式队列的优化

    链式队列的优化 上一节我们讲了一下顺序队列的优化,本节我们讲一下链式队列的优化.同理,我们得先知道链式队列的瓶颈在哪里. 链式队列的瓶颈 1.线性表的第一个元素作为队头,线性表的最后一个元素作为队尾: ...

  2. 【数据结构】顺序队列的实现(C语言)

    队列的基本概念及其描述 队列是一种特殊的线性表,它的特殊性在于队列的插入和删除操作分别在表的两端进行. 插入的那一端称为队尾,删除的那一端称为队首.队列的插入操作和删除操作分别称为进队和出队. 先进先 ...

  3. 数据结构之顺序队列和链式队列常用的一些操作

    顺序队列是队列的顺序存储结构,顺序队列实际上是运算受限的顺序表.和顺序表一样,顺序队列用一个向量空间来存放当前队列中的元素.由于队列的队头和队尾的位置是变化的,设置两个指针front和rear分别指示 ...

  4. (c语言数据结构)用顺序队列的方式实现输入12345,输出12345操作——期末数据结构程序设计

    用顺序队列的方式实现输入123456,输出12345操作 文章目录 用顺序队列的方式实现输入123456,输出12345操作 1.队列的定义 2.队列的初始化 3.判空操作 4.入队操作 5. 出队操 ...

  5. 浅谈数据结构之顺序队列(五)

    队列:是指只允许在一端进行插入操作,而在另一端进行删除操作的线性表.队列是一种先进先出的线性表,这与栈的后进先出正好相反:其中允许插入的一端我们称为队尾,允许删除的一端我们称为队头(或队首).假设队列 ...

  6. 数据结构(二):线性表包括顺序存储结构(顺序表、顺序队列和顺序栈)和链式存储结构(链表、链队列和链栈)...

    还记得数据结构这个经典的分类图吧: 今天主要关注一下线性表. 什么是线性表 线性表的划分是从数据的逻辑结构上进行的.线性指的是在数据的逻辑结构上是线性的.即在数据元素的非空有限集中 (1) 存在唯一的 ...

  7. 【数据结构】队列-顺序队列、循环队列、链队、双端队列

    定义 队列是只允许在一端进行插入,而在另一端进行删除的线性表. 队头(Front):允许删除的一端,又称为队首. 队尾(Rear): 允许插入的一端. 先进入队列的元素必然先离开队列,即先进先出(Fi ...

  8. 数据结构 队列(顺序队列 循环队列 链队列)

    目录 一.引入 二.队列的定义 三.队列的抽象数据类型 四.队列的存储方式 五.队列的顺序存储(不太常用 后面5.4会给出原因) 5.1顺序存储队列的基本知识点 5.2队列的顺序存储描述 5.3顺序存 ...

  9. 数据结构与算法(3-2)队列(顺序队列、循环队列与链队列)

    目录 一.顺序队列 1.存储结构 2.入队和出队 总代码 二.循环队列 总代码: 三.链队列 1.存储结构 2.入队和出队 总代码 一.顺序队列 队列特征:先进后出.后进后出. 1.存储结构 //队列 ...

最新文章

  1. 盘点:2020 年机器学习 10 大进展
  2. 3、spring注解注入
  3. java用redis缓存的步骤_详解在Java程序中运用Redis缓存对象的方法|chu
  4. 如何修改浏览器的默认滚动条样式
  5. 最新 Unity3D鼠标滑轮控制物体放大缩小 [
  6. 苹果笔记本单独安装win10
  7. canvas转化为图片并下载
  8. Linux-shell获取天气
  9. python中执行shell命令_python中执行shell命令的几个方法小结-阿里云开发者社区
  10. DeepMind为明年的AAAI,准备了一份各种DQN的混血
  11. RAR Extractor Max for Mac(解压缩软件)
  12. Gut Microbes:南医大刘星吟组-孤独症的基因变异与肠道微生物群、代谢物和细胞因子的改变有关...
  13. uploadify3.1 php,Jquery上传插件 uploadify v3.1使用说明_jquery
  14. Axure RP 8 获取焦点的应用
  15. 用qt 编译qt moc
  16. 把撒哈拉沙漠变成一个太阳能农场,这可能吗?
  17. java chmod 777_尽管使用chmod 777,但java.io.FileNotFoundException(权限被拒绝)
  18. 苹果手机怎样录屏 如何录制手机内容
  19. filter_input
  20. IT大佬告诉你大数据有哪些特点,新人学习必知

热门文章

  1. python自定义assert抛出的异常
  2. Linux定时向目标服务器传输文件
  3. linux5.5 分辨率,Linux Kernel 5.5 正式发布
  4. java http zip参数,如何从Web API 2 HttpGet发送zip文件
  5. rust最低什么显卡能游戏_腐蚀Rust配置要求汇总 腐蚀Rust游戏配置要求是什么_游侠网...
  6. 【thinkphp】ThinkPHP各个低版本(=3.2)完全配置参考手册
  7. 【设计模式】适配器模式 Adapter Pattern
  8. 龙应台--为什么我要求你读书用功
  9. Maven--部署构件至 Nexus
  10. java第一次作业计科2班马浩加