文章首发:http://pjf.name/post-119.html
本文基于"姓名标识-非商业性-相同方式分享 4.0国际"协议创作或转载,转载原创文章请注明来源于疯子的自留地,否则请勿转载或再转载,谢谢合作:)
先来说下队列.其实就是线性表的变种.遵循先进先出,即删除数据的位置为头结点,新增数据的位置为尾结点.恩,就是这么简单...
好了,按照在线性表的顺序存储我们知道了如果我们删除一个数据的话那么时间复杂度为0(N),既然我们现在知道了我们每次删除的都是头结点,咱们定义一个int性的front来存储头结点的下标,那么我们的复杂度就是0(1)了不是,增加数据也就简单了,搞一个int型的rear来存储尾结点的下标,然后增加数据的时间复杂度也为0(1)了,Wow,cool...但是...咱们就想了啊,如果加入在一个可以存储10个数据的队列里,先一口气插入了10个数据,接下来,我们删除前9个数据,那么现在front和rear的值都是9了对不对,好了,我们再新增一个数据,额,都到了数组末尾了,sorry.不能新增了...可是...可是...前面空了9个位置啊亲!咋就不能灵活点嘛!于是乎就有了循环队列.即rear到达了数组末尾的时候再新增数据rear值移到0即数组开头不就行了!好了,有个问题又来了,咱们如何判断队列是满了呢?当rear==front的时候?嘿嘿,那你估计一辈子都插不进数据了,咱们刚开始的时候不是rear就等于front嘛...那咱们再设一个bool型的flag,初始化的时候flag=0表示队列空,然后当满的时候flag设置为1,这样不就解决了问题了嘛,赞一个,确实可以如此,不过也可以这样,那就是咱们留一个位置来不放数据,即(rear+1)%MAXSIZE==Front的时候表示队列满了.ok,上数据结构和代码:
队列结构:
typedef struct{
char Data[MAXSIZE];
int Front;
int Rear;
}Queue;
1.初始化:
BOOL InitializeQueue(Queue *Q)
{
Q->Rear=Q->Front=0;
return true;
}
2.插入数据:
BOOL InsertDataQueue(Queue *Q,char InsertData)
{
if(Q->Front==(Q->Rear+1)%MAXSIZE)//if the queue is full,return false
return false;
Q->Data[Q->Rear]=InsertData;
Q->Rear=(Q->Rear+1)%MAXSIZE;//position of rear move to next adress,move to the head if the Q->Rear+1 is equal to MAXSIZE
return true;
}
3.删除数据:
BOOL DeleteDataQueue(Queue *Q,char *DeleteData)
{
if(Q->Front==Q->Rear)//if the queue is empty, return false
return false;
*DeleteData=Q->Data[Q->Front];
Q->Data[Q->Front]=0;
Q->Front=(Q->Front+1)%MAXSIZE;
return true;
}
4.取得队列头数据:
BOOL GetHead(Queue Q,char *HeadData)
{
if(Q.Rear==Q.Front)
return false;
*HeadData=Q.Data[Q.Front];
return true;
}
5.队列长度:
int QueueLength(Queue Q)
{
return (Q.Rear-Q.Front+MAXSIZE)%MAXSIZE;
}
6.清空队列:
BOOL ClearQueue(Queue *Q)
{
int temp;
if(Q->Rear==Q->Front)
return false;
Q->Front=Q->Rear=0;
return true;
}
7.队列是否为空:
BOOL isQueueEmpty(Queue Q)
{
if(Q.Rear==Q.Front)
return true;
return false;
}
写个完整的程序测试下:
#define true 1
#define false 0
#define BOOL int
#define MAXSIZE 27
#include<stdlib.h>
#include<stdio.h>
int main(void)
{
Queue Q;
char InputData='a',DeleteData;
int temp;
if(false==InitializeQueue(&Q))
{
printf("Initialize queue fail!\n");
return false;
}
printf("Initialize queue success!\n");
for(temp=0;temp<MAXSIZE-1;temp++)
{
if(false==InsertDataQueue(&Q,InputData))
{
printf("Insert data %c fail!\n",InputData);
}
printf("Insert data %c success!\n",InputData);
InputData++;
}
printf("Success to create a queue which length is %d\n",QueueLength(Q));
if(false==DeleteDataQueue(&Q,&DeleteData))
printf("Fail to delete Data from the length!\n");
printf("Success to delete the data %c,the length of new queue is %d\n",DeleteData,QueueLength(Q));
if(false==ClearQueue(&Q))
printf("Fail to Clear the queue's data!\n");
printf("Success to clear the queue's data!the new length of queue is %d\n",QueueLength(Q));
return 0;
}
运行截图:
接下来说下队列的链式结构,既然是链式结构了,那肯定就是线性表的链式存储的变体了,不错,就是尾结点插入,头结点删除.其它的没啥好说的,就是注意指针的运用,直接上数据结构和代码:
队列结构:
typedef struct QueueList{
char Data;
struct QueueList *next;
}Node,*QueueHeader;
1.初始化:
BOOL InitializeQueue(QueueHeader *QH)
{
*QH=(QueueHeader)malloc(sizeof(QueueHeader));
if(!QH)
return false;
(*QH)->Data=0;
(*QH)->next=NULL;
return true;
}
2.插入数据:
BOOL InsertDataQueue(QueueHeader *QH,char InputData)
{
Node *NewEndNode,*EndNode;
int temp;
NewEndNode=(Node*)malloc(sizeof(Node));
if(!NewEndNode)
return false;
NewEndNode->next=NULL;
NewEndNode->Data=InputData;
EndNode=*QH;
for(temp=0;temp<(*QH)->Data;temp++)
EndNode=EndNode->next;
EndNode->next=NewEndNode;
(*QH)->Data++;
return true;
}
3.删除数据:
BOOL DeleteDataQueue(QueueHeader *QH,char *OutputData)
{
Node *DeleteNode;
if(true==isQueueEmpty(*QH))
return false;
DeleteNode=(*QH)->next;
(*QH)->next=DeleteNode->next;
(*QH)->Data--;
free(DeleteNode);
return true;
}
4.取得队列头数据:
BOOL TopQueue(QueueHeader QH,char *TopValue)
{
if(true==isQueueEmpty(QH))
return false;
*TopValue=QH->next->Data;
return true;
}
5.队列长度:
int QueueLength(QueueHeader QH)
{
return QH->Data;
}
6.清空队列:
BOOL EmptyQueue(QueueHeader QH)
{
char DeleteTemp;
if(true==isQueueEmpty(QH))
return false;
while(QH->next!=NULL)
DeleteDataQueue(&QH,&DeleteTemp);
return true;
}
7.销毁队列:
BOOL DestroyQueue(QueueHeader QH)
{
if(false==isQueueEmpty(QH))
EmptyQueue(QH);
free(QH);
return true;
}
8.队列是否为空:
int isQueueEmpty(QueueHeader QH)
{
if(NULL==QH->next)
return true;
return false;
}
写个完整的程序测试下:
#define true 1
#define false 0
#define BOOL int
#include<stdlib.h>
#include<stdio.h>
int main(void)
{
QueueHeader Q;
char InsertData='a',DeleteData;
printf("Now we start to Initialize a queue...\n");
if(false==InitializeQueue(&Q))
{
printf("Sorry,initialize a queue fail!\n");
return -1;
}
printf("Congratulation!Initialize queue success!\n");
printf("Now we start to insert the character 'a' to 'z' to the queue...\n");
while(Q->Data!=26)
{
if(false==InsertDataQueue(&Q,InsertData))
printf("Fail to insert value %c to queue\n",InsertData);
printf("Success to insert value '%c' to queue\n",InsertData);
InsertData++;
}
TopQueue(Q,&DeleteData);
printf("Success to insert characters 'a' to 'z'.The queue's length is %d and the top value in the queue is %c\n",QueueLength(Q),DeleteData);
printf("Now we plan to Delete a data from the queue...\n");
if(false==DeleteDataQueue(&Q,&DeleteData))
{
printf("Sorry,fail to delete the data from the queue!\n");
}
TopQueue(Q,&InsertData);
printf("Success to delete the data %c from the queue!The queue length now is %d and first value in the queue is %c\n",DeleteData,QueueLength(Q),InsertData);
printf("OK,Why we don't insert the character '@' to the queue?Now let us do it!\n");
if(false==InsertDataQueue(&Q,'@'))
printf("Sorry,fail to insert character '@' to the queue!\n");
printf("Ok,now we have inserted the character '@' to the queue!the newest length of the queue is %d\n",QueueLength(Q));
return 0;
}
运行截图: