在学习数据结构中,队列也是一个重要的数据结构,我们今天来用基于顺序表的队列(Queue),
在基于顺序表队列如果是不循环的顺序表,则在出队列时,时间复杂度是O(n),所以我们用循环队列来
实现,怎么解释基于循环顺序表的队列呢?
我们上图:
上图是在不循环顺序表中出队。这样不难看出时间复杂度不是很好。
所以我们来顺序循环队列,把顺序表让它循环利用。
看图
上图就是顺序表循环队列,a就是队首,d就是队尾,这样可以避免出队后移位,所以就时间复杂度更小。
那么咱们来看代码:
先是声明:
#pragma once
#include<stdio.h>
#define MAXREPOSITORY 10
#define TEAM_HEAD printf("\n===========%s==========\n",__FUNCTION__)
typedef char QueueType;
typedef struct SeqQueue{
size_t count;
size_t size;
QueueType data[MAXREPOSITORY];
}SeqQueue;
// 初始化。
void InitSeqQueue(SeqQueue *seq);
// 入队。
void PushQueue(SeqQueue *seq,QueueType value);
// 出队。
void PopQueue(SeqQueue *seq);
// 取队首元素。
QueueType FindHead(SeqQueue *seq);
// 取队尾元素。
QueueType FindBottom(SeqQueue *seq);
// 销毁。
void DestoryQueue(SeqQueue *seq);
看定义:
#include"SeqQueue.h"
// 初始化。
void InitSeqQueue(SeqQueue *seq)
{
if (seq == NULL)
{
return;
}
seq->size = 0;
seq->count = 0;
}
// 入队。
void PushQueue(SeqQueue *seq,QueueType value)
{
if (seq == NULL)
{
return;
}
if (seq->count == MAXREPOSITORY)
{
// 队列满。
return;
}
// 当循环顺序队循环完但队未满时,进行循环。
if (seq->size > MAXREPOSITORY)
{
seq->size = 0;
}
seq->data[seq->size] = value;
++seq->size;
++seq->count;
}
// 出队。
void PopQueue(SeqQueue *seq)
{
if (seq == NULL)
{
return;
}
if (seq->count == 0)
{
// 空队列。
return;
}
--seq->count;
}
// 取队尾元素。
QueueType FindButtom(SeqQueue *seq)
{
if (seq == NULL)
{
printf("输入错误\n");
return 0;
}
if (seq->count == 0)
{
printf("队为空\n");
return 0;
}
return seq->data[seq->size-1];
}
// 取队首元素。
QueueType FindHead(SeqQueue *seq)
{
if (seq == NULL)
{
printf("输入错误\n");
return 0;
}
if (seq->count == 0)
{
printf("队为空\n");
return 0;
}
if (seq->size >= seq->count)
{
return seq->data[seq->size - seq->count];
}
else
{
size_t tmp = seq->count-seq->size;
size_t size = MAXREPOSITORY;
return seq->data[size-tmp];
}
}
// 销毁。
void DestoryQueue(SeqQueue *seq)
{
if (seq == NULL)
{
return;
}
seq->size = 0;
seq->count = 0;
}
//以下为测试代码
void PrintSeqQueue(SeqQueue *seq)
{
if (seq == NULL)
{
return;
}
printf("[队尾]->");
size_t count = 0;
size_t size = seq->size;
if (size != 0)
{
while (seq->count > count)
{
printf("[%c]->",seq->data[size-count-1]);
count++;
}
// for (; count < seq->count; ++count)
// {
// printf("[%c]<-",seq->data[count]);
// }
}
else
{
while (seq->count > count)
{
// 当循环到最大size但是队未满。
if (size - count - 1 == 0)
{
printf("[%c]->",seq->data[size-count-1]);
size = MAXREPOSITORY;
count++;
}
else
{
printf("[%c]->",seq->data[size-count-1]);
count++;
}
}
// for(; count < seq->count; ++count)
// {
// if (size-count == 0)
// {
// size = MAXREPOSITORY;
// }
// printf("[%c]<-",seq->data[size-count]);
// }
}
printf("[队头]\n");
}
// 顺序队的初始化。
void TestInitSeqQueue()
{
TEAM_HEAD;
SeqQueue seq;
InitSeqQueue(&seq);
}
void TestPushQueue()
{
TEAM_HEAD;
SeqQueue seq;
InitSeqQueue(&seq);
PushQueue(&seq, 'a');
PushQueue(&seq, 'b');
PushQueue(&seq, 'c');
PushQueue(&seq, 'd');
PrintSeqQueue(&seq);
}
void TestPopQueue()
{
TEAM_HEAD;
SeqQueue seq;
InitSeqQueue(&seq);
PushQueue(&seq, 'a');
PushQueue(&seq, 'b');
PushQueue(&seq, 'c');
PushQueue(&seq, 'd');
PushQueue(&seq, 'e');
PrintSeqQueue(&seq);
PopQueue(&seq);
PopQueue(&seq);
PopQueue(&seq);
PopQueue(&seq);
PrintSeqQueue(&seq);
PushQueue(&seq, 'f');
PushQueue(&seq, 'g');
PushQueue(&seq, 'h');
PushQueue(&seq, 'i');
PushQueue(&seq, 'j');
PushQueue(&seq, 'k');
PrintSeqQueue(&seq);
}
void TestFindButtom()
{
TEAM_HEAD;
SeqQueue seq;
InitSeqQueue(&seq);
PushQueue(&seq, 'a');
PushQueue(&seq, 'b');
PushQueue(&seq, 'c');
PushQueue(&seq, 'd');
PushQueue(&seq, 'e');
PrintSeqQueue(&seq);
QueueType ret = FindButtom(&seq);
printf("except e actual %c",ret);
}
void TestFindHead()
{
TEAM_HEAD;
SeqQueue seq;
InitSeqQueue(&seq);
PushQueue(&seq, 'a');
PushQueue(&seq, 'b');
PushQueue(&seq, 'c');
PushQueue(&seq, 'd');
PushQueue(&seq, 'e');
PrintSeqQueue(&seq);
PopQueue(&seq);
PopQueue(&seq);
PopQueue(&seq);
PopQueue(&seq);
PrintSeqQueue(&seq);
PushQueue(&seq, 'f');
PushQueue(&seq, 'g');
PushQueue(&seq, 'h');
PushQueue(&seq, 'i');
PushQueue(&seq, 'j');
PushQueue(&seq, 'k');
PrintSeqQueue(&seq);
QueueType ret = FindHead(&seq);
printf("except e actual %c",ret);
}
void TestDestoryQueue()
{
TEAM_HEAD;
SeqQueue seq;
InitSeqQueue(&seq);
PushQueue(&seq, 'a');
PushQueue(&seq, 'b');
PushQueue(&seq, 'c');
PushQueue(&seq, 'd');
PushQueue(&seq, 'e');
PrintSeqQueue(&seq);
DestoryQueue(&seq);
PrintSeqQueue(&seq);
}
int main()
{
TestInitSeqQueue();
TestPushQueue();
TestPopQueue();
TestFindButtom();
TestFindHead();
TestDestoryQueue();
return 0;
}
顺序表循环队列中,最需要注意的就是在顺序表到达最大位置时,
需要将size置为0,所以我们添加了一个变量count来计数队中元素的个数,
这样就可以判断队列是否满,还有在打印队列中也需要注意打印的顺序,是从前往后打印还是相反
要明确。我呢,是采用从队尾打印,也就是先打印呢size值大的。
如有不足请多多指教。