1、队列的定义
- 队列是一种特殊的线性表
- 队列仅在线性表的两端进行操作
- 队头( Front):取出数据元素的一端
- 队尾( Rear):插入数据元素的一端
- 队列不允许在中间部位进行操作!
2、队列的性质
性质:先进先出(FIFO)
3、队列的顺序存储实现
示意图:
4、代码复用
利用顺序链表,实现顺序存储的队列!
/*
在队尾添加一个元素
如果成功,返回1,失败返回0
*/
int SeqQueue_Append(SeqQueue *queue, SeqQueueNode *item) //O(1)
{
//将线性表的尾部定义为队列的尾部
return List_Insert(queue,item,List_Length(queue));
}
/*
在队头移出一个元素
如果成功,返回被移出的元素指针,否则,返回NULL
*/
SeqQueueNode *SeqQueue_Retrieve(SeqQueue *queue) //O(n)
{
return List_Delete(queue,0);
}
经过时间复杂度的分析,常用操作SeqQueue_Append();的时间复杂度为O(1),但是SeqQueue_Retrieve();操作的时间复杂度却是O(n),所以有了以下改进的算法!
5、顺序队列的优化方案
SeqQueue_Retrieve();操作,因为删除的是顺序链表的第1个元素,所以每次都需要把后面的元素依次向前移动一位,这就增加了时间复杂度!
- 定义front使其始终代表队头的下标
- 出队时将队头元素返回,且front++
- 定义rear使其始终代表队尾下一个元素的下标
- 入队时将新元素插入,且rear++
- 没有必要只将下标为0的位置定义为队头!!!
6、改进的算法
数据结构的定义:
/*
为了保持对外的接口一致
*/
typedef void SeqQueue;
typedef void SeqQueueNode;
/*
内部实现的具体定义
*/
#ifdef WIN32
typedef unsigned int TSeqQueueNode;
#else
typedef unsigned long TSeqQueueNode;
#endif
//增加了front和rear成员,用于标记队头和队尾
typedef struct _struct_SeqQueue
{
int capacity;
int length;
int front;
int rear;
TSeqQueueNode *node;
}TSeqQueue;
部分代码:
/*
在队尾添加一个元素
如果成功,返回1,失败返回0
*/
int SeqQueue_Append(SeqQueue *queue, SeqQueueNode *item) //O(1)
{
int iret = 1;
TSeqQueue *tqueue = (TSeqQueue*)queue;
iret = iret && (tqueue != NULL) && (item != NULL);
if(iret)
{
//判断是否有位置可以插入
iret = tqueue->length < tqueue->capacity;
if(iret)
{
//在当前队尾的位置插入数据,注意保存的是地址值
tqueue->node[tqueue->rear] = (TSeqQueueNode)item;
//让队尾向后移动一个位置,如果超出数组,则重新指向0号位置
//此时数组是循环利用的
tqueue->rear = (tqueue->rear + 1) % tqueue->capacity;
tqueue->length++;
}
}
return iret;
}
/*
在队头移出一个元素
如果成功,返回被移出的元素指针,否则,返回NULL
*/
SeqQueueNode *SeqQueue_Retrieve(SeqQueue *queue) //O(1)
{
TSeqQueueNode *ret = NULL;
TSeqQueue *tqueue = (TSeqQueue*)queue;
if(tqueue != NULL)
{
//判断是否还有元素可取
if(tqueue->length > 0)
{
ret = (SeqQueueNode*)tqueue->node[tqueue->front];
//让队头向后移动一个位置,如果超出了数组,则指向0号位置
tqueue->front = (tqueue->front + 1) % tqueue->capacity;
tqueue->length--;
}
}
return ret;
}
7、完整源码下载
文件名:seqqueue-1.0.tar.gz
说明:利用顺序链表实现的顺序队列
链接: http://pan.baidu.com/s/1kTnDpaf 密码: b7di
文件名:seqqueue-2.0.tar.gz
说明:未使用顺序链表,采用改进的算法重新实现的顺序队列
链接: http://pan.baidu.com/s/1i3Ij6g1 密码: eixe
编译步骤:
0.1 解压缩:tar -zxvf seqqueue-1.0.tar.gz/seqqueue-2.0.tar.gz
0.2 进入目录:./configure
0.3 生成Seqlist:make
0.4 运行程序:./SeqQueue