数据结构(队列)
队列是一种仅限在数据末尾进行增加数据和数据起始减少数据的数据结构,其特点为先进先出(FIFO)。
其基本操作与栈的操作类似,不同的删除数据在队头进行。
队列的存储分为两种,顺序表示与链式表示。
与顺序栈相似,我们需要一个连续的存储单元,依次存放数据,尚需尚需附设两个整型变量 front 和 rear分别指示队列头元素及队列尾元素的位置(即称头指针,尾指针)。
这里将数据简单化处理为int类型,则有:
#define MAXSIZE 1000
tyepdef struct queue{
int data[MAXSIZE];//数据空间
int front;//队头索引
int rear;//队尾索引
}queue;
类似与数组,为实现增加与减少操作,在初始化时,令front = rear = 0;每当插入新的数据时,rear+1,每当删队头元素时,front+1。因此,在非空队列中,front始终指向队头元素,rear始终指向队尾元素的下一位置。
此时,不断的增加和减少元素,导致front,rear不断增加,会出现两指针不断接近连续空间的末尾,最后可能出现数据的溢出,而此时连续空间的起始部分可能并未占满,所以称这种现象为“假溢出”
为解决这一问题,使用循环队列,即当数据指针到达空间末端后,对其求模,使其回到初始位置,充分利用空间。
//初始化队列
#define MAXSIZE 1000
queue* initQueue(){
queue* q = (queue*)malloc(sizeof(queue));
q->front = q->rear = 0;//将索引初始化
return q;
}
//获得队列长度
int Queue_Length(queue* obj,int val){
return (obj->rear - obj->front + MAXSIZE)%MAXSIZE;
/*防止出现队尾索引小于队头索引情况,对其加最大容量后,对其求模*/
//增加队尾元素
void QueuePush(queue* obj){
if((obj->rear + 1)%MAXSIZE != obj->front){//加1即为下一元素,还需注意是否越界访问,队列是否满的问题
obj->data[obj->rear] = val;
obj->rear = (obj->rear + 1)/MAXSIZE;
}
}
//删除队头元素
void Queue_Pop(queue* obj){
if(((obj->rear +1)%MAXSIZE != obj->front)){
obj->front = (obj->front+1)%MAXSIZE;//加1指向下一元素即可。
}
}
//获取队头元素
int Queue_getFront(queue* obj){
if(obj->front != obj->rear){//需判断是否为空的问题
return obj->data[obj->front];
}
return -1;//为空则返回-1
}
链式存储结构
typedef struct QNode{
int data;//数据域
struct QNode* next;//指针域
}QNode;
//类似的,需要头,尾指针。
typedef struct{
struct QNode* front;//需要头,尾指针对元素进行操作
struct QNode* rear;
}Q;
//初始化队列
QNode* initQueue(){
Q.front = Q.rear = (QNode*)malloc(sizeof(QNode));
Q.front->data = 0;
Q.front->next = NULL;//置空,避免野指针
}
//入队
void push(QNode* obj, int val){
QNode* temp = (QNode*)malloc(sizeof(QNode));
temp->data = val;
temp->next = NULL;
Q.rear->next =temp;//注意从队尾加入数据
Q.rear = temp;//链接上新节点
}
//出队
int pop(QNode* obj,int val){
int flag = 0;
if(Q.front != Q.rear){
QNode* temp = Q.front->next;
val = temp->data;//取出并删除队头元素
flag = 1;//记录下队列不为空
Q.front->next = temp->next;
if(temp == Q.rear){
Q.rear = Q.front;
}
free(temp);//注意释放内存
}
if(flag){//队列不为空,则返回删除的数据,否则返回-1
return val;
}
else{
return -1;
}
//获取队首的值
int Get_Queuefront(QNode* obj){
if(Q.front != Q.rear){
return Q.front->next->data;//注意头节点的数据域无效
}
}