数据--第23课 - 队列的优化实现

第23课 - 队列的优化实现

1. 顺序队列的瓶颈

顺序队列

线性表的第一个元素作为队头。

线性表的最后一个元素作为队尾。

入队的新元素是线性表的最后,时间复杂度为O(1)。

出队列时需要将后续的所有元素向前移动,时间复杂度是O(n)。

2. 顺序队列的优化方案

(1)定义front使其始终代表队头的下标。

出队列时对头元素返回,且front++

(2)定义rear使其始终代表队尾下一个元素的下标。

出队时将新的元素插入,且rear++

(3)没有必要只将下标为0的位置定义为队头。

(4)顺序队列的关键状态

初始状态:length == 0,front == 0,rear == 0;

空队列状态:length == 0,front == rea;
         满队列状态:length == capacity,front == rea;

(5)循环使用队列的空间

入列:rear = (rear + 1) % capacity;

出列:front = (front + 1) % capacity;

3. 程序

(1)LinkQueue2.0

main.c

#include
<stdio.h>

#include
<stdlib.h>

#include
"LinkQueue.h"

/* run this
program using the console pauser or add your own getch,
system("pause") or input loop */

int main(int
argc, char *argv[])

{

LinkQueue* queue = LinkQueue_Create();

int a[10] = {0};

int i = 0;

for(i=0; i<10; i++)

{

a[i] = i + 1;

LinkQueue_Append(queue, a + i);

}

printf("Header: %d\n",
*(int*)LinkQueue_Header(queue));

printf("Length: %d\n",
LinkQueue_Length(queue));

LinkQueue_Clear(queue);

while( LinkQueue_Length(queue) > 0 )

{

printf("Retrieve: %d\n",
*(int*)LinkQueue_Retrieve(queue));

}

LinkQueue_Destroy(queue);

return
0;

}

LinkQueue.h

#ifndef
_LINKQUEUE_H_

#define
_LINKQUEUE_H_

typedef void
LinkQueue;

LinkQueue*
LinkQueue_Create();

void LinkQueue_Destroy(LinkQueue*
queue);

void
LinkQueue_Clear(LinkQueue* queue);

int
LinkQueue_Append(LinkQueue* queue, void* item);

void*
LinkQueue_Retrieve(LinkQueue* queue);

void*
LinkQueue_Header(LinkQueue* queue);

int
LinkQueue_Length(LinkQueue* queue);

#endif

LinkQueue.c

#include
<malloc.h>

#include
<stdio.h>

#include
"LinkQueue.h"

typedef struct
_tag_LinkQueueNode TLinkQueueNode;

struct
_tag_LinkQueueNode

{

TLinkQueueNode* next;

void* item;

};

typedef struct
_tag_LinkQueue

{

TLinkQueueNode* front;

TLinkQueueNode* rear;

int length;

} TLinkQueue;

LinkQueue*
LinkQueue_Create() // O(1)

{

TLinkQueue* ret =
(TLinkQueue*)malloc(sizeof(TLinkQueue));

if( ret != NULL )

{

ret->front = NULL;

ret->rear = NULL;

ret->length = 0;

}

return ret;

}

void
LinkQueue_Destroy(LinkQueue* queue) // O(n)

{

LinkQueue_Clear(queue);

free(queue);

}

void
LinkQueue_Clear(LinkQueue* queue) // O(n)

{

while( LinkQueue_Length(queue) > 0 )

{

LinkQueue_Retrieve(queue);

}

}

int
LinkQueue_Append(LinkQueue* queue, void* item) // O(1)

{

TLinkQueue* sQueue = (TLinkQueue*)queue;

TLinkQueueNode* node =
(TLinkQueueNode*)malloc(sizeof(TLinkQueueNode));

int ret = (sQueue != NULL ) &&
(item != NULL) && (node != NULL);

if( ret )

{

node->item = item;

if( sQueue->length > 0 )

{

sQueue->rear->next = node;

sQueue->rear = node;

node->next = NULL;

}

else

{

sQueue->front = node;

sQueue->rear = node;

node->next = NULL;

}

sQueue->length++;

}

if( !ret )

{

free(node);

}

return ret;

}

void*
LinkQueue_Retrieve(LinkQueue* queue) // O(1)

{

TLinkQueue* sQueue = (TLinkQueue*)queue;

TLinkQueueNode* node = NULL;

void* ret = NULL;

if( (sQueue != NULL) &&
(sQueue->length > 0) )

{

node = sQueue->front;

sQueue->front = node->next;

ret = node->item;

free(node);

sQueue->length--;

if( sQueue->length == 0 )

{

sQueue->front = NULL;

sQueue->rear = NULL;

}

}

return ret;

}

void*
LinkQueue_Header(LinkQueue* queue) // O(1)

{

TLinkQueue* sQueue = (TLinkQueue*)queue;

void* ret = NULL;

if( (sQueue != NULL) &&
(sQueue->length > 0) )

{

ret = sQueue->front->item;

}

return ret;

}

int
LinkQueue_Length(LinkQueue* queue) // O(1)

{

TLinkQueue* sQueue = (TLinkQueue*)queue;

int ret = -1;

if( sQueue != NULL )

{

ret = sQueue->length;

}

return ret;

}

(2)SeqQueue2.0

main.c

#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;

}

SeqQueue.h

#ifndef
_SEQQUEUE_H_

#define
_SEQQUEUE_H_

typedef void
SeqQueue;

SeqQueue*
SeqQueue_Create(int capacity);

void
SeqQueue_Destroy(SeqQueue* queue);

void
SeqQueue_Clear(SeqQueue* queue);

int
SeqQueue_Append(SeqQueue* queue, void* item);

void*
SeqQueue_Retrieve(SeqQueue* queue);

void*
SeqQueue_Header(SeqQueue* queue);

int
SeqQueue_Length(SeqQueue* queue);

int
SeqQueue_Capacity(SeqQueue* queue);

#endif

SeqQueue.c   

#include
<stdio.h>

#include
<malloc.h>

#include
"SeqQueue.h"

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;

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;

}

void
SeqQueue_Destroy(SeqQueue* queue) // O(1)

{

free(queue);

}

void
SeqQueue_Clear(SeqQueue* queue) // O(1)

{

TSeqQueue* sQueue = (TSeqQueue*)queue;

if( 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);

if( 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);

if( 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;

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;

if( sQueue != NULL )

{

ret = sQueue->length;

}

return ret;

}

int
SeqQueue_Capacity(SeqQueue* queue) // O(1)

{

TSeqQueue* sQueue = (TSeqQueue*)queue;

int ret = -1;

if( sQueue != NULL )

{

ret = sQueue->capacity;

}

return ret;

}

4. 链式队列的瓶颈

链式队列

线性表的第一个元素作为队头。

线性表的最后一个元素作为队尾。

入队的新元素实在线性表的最后,时间复杂度是O(n)。

出队的元素即链表的第一个元素,时间复杂度是O(1)。

5. 优化方案

(1)定义rear指针始终指向链表的最后一个元素,入队时将新的元素通过rear插入队尾,而且将rear指向新的元素。

(2)链式队列的关键状态

空队列状态:front == NULL, rear == NULL;

关键操作:

入队:

rear ->next = node;

rear = node;

node ->next =NULL;

出列:

front = front ->next;

6. 代码

小结:

(1)      优化的顺序队列循环利用顺序空间提高队列操作的效率。

(2)      优化的链式队列定义rear指针指向队尾元素提高出队操作的效率。

(3)      效率提高了,可实现的复杂性也提高了。

原文地址:https://www.cnblogs.com/free-1122/p/11322848.html

时间: 2024-10-13 10:45:22

数据--第23课 - 队列的优化实现的相关文章

第18课——队列的优化实现

之前实现的顺序栈和链式栈的进栈和出栈操作时间复杂度都是O(1).而用同样的方式实现队列,进队和出队的复杂度总有一个是O(n) .顺序队列的瓶颈 顺序队列 线性表的第一个元素作为队头 线性表的最后一个元素作为队尾 入队的新元素是在线性表的最后,时间复杂度为O(1): 出队时需要将后续的所有元素向前移动,时间复杂度为O(n): 顺序队列的优化方案 定义顺序队列的头: typedef unsigned int TSeqQueueNode; typedef struct _tag_SeqQueue {

C++--第23课 - STL简介

第23课 - STL简介 1. 标准模板SLT C++的作用就是提高程序书写的效率,那么就得代码复用. STL,即:Standard Template(样板) Library,是C++的一部分(常用的数据结构).STL是常用数据结构和算法的集合.STL的目标是标准化组件,提高开发效率和程序可靠性. STL库作为为C++的一部分与编译器一同被发布.STL主要由以下3个部分组成: 容器(Container):管理数据的集合 算法(Algorithm):处理集合内的元素 迭代器(Iterator):遍

[转]浅析大数据量高并发的数据库优化

链接:http://www.uml.org.cn/sjjm/201308264.asp 高并发数据库可以同时处理海量信息,应用范围很广.今天我们将讨论的是大数据量高并发的数据库优化,希望对大家有所帮助. 一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. 在一个系统分析.设计阶段,因为数据量较小,负荷较低.我们往往只注意到功能的实现,而很难注意到性

(转)大数据量高并发的数据库优化与sql优化

大数据量高并发的数据库优化 一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. 在一个系统分析.设计阶段,因为数据量较小,负荷较低.我们往往只注意到功能的实现,而很难注意到性能的薄弱之处,等到系统投入实际运行一段时间后,才发现系统的性能在降低,这时再来考虑提高系统性能则要花费更多的人力物力,而整个系统也不可避免的形成了一个打补丁工程. 所以在考虑整

微信后台异步消息队列的优化升级实践分享

1.引言 MQ 异步消息队列是微信后台自研的重要组件,广泛应用在各种业务场景中,为业务提供解耦.缓冲.异步化等能力.本文分享了该组件2.0版本的功能特点及优化实践,希望能为类似业务(比如移动端IM系统等)的消息队列设计提供一定的参考. 2.关于分享者 廖文鑫,2013年加入腾讯,从事微信后台基础功能及架构的开发和运营,先后参与了消息通知推送系统.任务队列组件.春晚摇红包活动等项目,在海量分布式高性能系统方面有丰富的经验. 3.背景介绍 微信后台给件 MQ 1.0 发布之初,基本满足了一般业务场景

23条前端性能优化,看懂就够了!

前端性能优化是个巨大的课题,如果要面面俱到的说的话,估计三天三夜说不完.所以我们就从实际的工程应用角度出发,聊我们最常遇见的前端优化问题. 1. 减少HTTP请求次数 尽量合并图片.CSS.JS.比如加载一个页面,如果有5个css文件的话,那么会发出5次http请求,这样会让用户第一次访问你的页面的时候会长时间等待.而如果把这个5个文件合成一个的话,就只需要发出一次http请求,节省网络请求时间,加快页面的加载. 2. 使用CDN 网站上静态资源即css.js全都使用cdn分发,图片亦然. 3.

七月算法--12月机器学习在线班-第四次课笔记—凸优化

七月算法--12月机器学习在线班-第四次课笔记—凸优化 七月算法(julyedu.com)12月机器学习在线班学习笔记 http://www.julyedu.com

DevExpress ChartControl大数据加载时有哪些性能优化方法

DevExpress ChartControl加载大数据量数据时的性能优化方法有哪些? 关于图表优化,可从以下几个方面解决: 1.关闭不需要的可视化的元素(如LineMarkers, Labels等): Series.View.LineMarkerOptions.Visible =false. 2. 关闭图表的滚动与缩放功能,手动调整范围,这样将大大减少所需计算的个数. 3. 将 ChartControl.RefreshDataOnRepaint属性设为false 4. 将 ChartContr

HDU 3507 单调队列 斜率优化

斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方法来做,但是该题要求的是区间和的平方,于是要转换单调的计算方法为斜率,也就是凸线. 其他就是最基本的单调DP /** @Date : 2017-09-04 15:39:05 * @FileName: HDU 3507 单调队列 斜率优化 DP.cpp * @Platform: Windows * @