一、简述
记--顺序存储队列、链式存储队列;其中顺序存储队列又分为循环队列和非循环队列。
队列简称队,它是一种操作受限的线性表,其限制为仅允许在表的一端进行插入(插入的一端称为队首,front),在表的另一端进行删除(删除的一端称为队尾)。插入新的元素称为进队或入队,删除元素也称为出队或离队。由于队列的一端只能插入,另一端只能删除,每个元素必然按照进队的顺序排列(出队),所以又把队列称为先进先出表。
二、顺序存储队列
2.1 非循环顺序存储队列
例子:队的大小设置为5, 输入正数--〉入队,输入负数--〉出队, 输入0--〉退出
代码结构:
测试代码1:
#include
#include //memset()
#define SIZE 5
typedef struct s_queue
{
int data[SIZE];
int front; //队首
int rear; //队尾
}Queue;
/*函数声明*/
void init_queue(Queue *queue);
int is_empty(Queue *queue);
int push_queue(Queue *queue, int input);
int pop_queue(Queue *queue, int *output);
void display_queue(Queue *queue);
int main(int argc, char *argv[])
{
Queue queue;
init_queue(&queue);//初始化队列
int input, ret, output;
while(1)
{
scanf("%d", &input);
if( input > 0 )//进队
{
ret = push_queue(&queue, input);
if( ret == 0)
{
display_queue( &queue );//打印队列的所有元素
}
else
{
printf("push data to queue is failed\n");
}
}
else if( input < 0 )//出队
{
ret = pop_queue(&queue, &output);
if( ret == 0)
{
printf("出队的元素是[%d]\n", output);
display_queue( &queue );
}
else
{
printf("pop data from queue is failed\n");
}
}
else if(input == 0)//退出
{
break;
}
}
return 0;
}
void init_queue(Queue *queue)//初始化队列
{
memset(queue, 0, sizeof(*queue));//清零
queue->front = -1;
queue->rear = -1;
}
int is_empty(Queue *queue)//判断队列是否为空
{
return queue->front == queue->rear;
}
int is_full(Queue *queue)//判断队列是否满了
{
return queue->rear == (SIZE - 1);
}
int push_queue(Queue *queue, int input)//元素入队
{
if( is_full(queue) == 1 )
{
return -1;
}
queue->rear++;
queue->data[queue->rear] = input;
return 0;
}
int pop_queue(Queue *queue, int *output)//元素出队,出队的元素存放到output
{
if( is_empty(queue) == 1 )
{
return -1;
}
queue->front++;
*output = queue->data[queue->front];
return 0;
}
void display_queue(Queue *queue)//打印队列所有元素
{
if( is_empty(queue) == 1)
{
printf("the queue is empty\n");
return ;
}
printf("队首 ");
int i;
for(i=queue->front+1; i<=queue->rear; i++ )
{
printf("[%d] ", queue->data[i]);
}
printf("队尾\n");
}
运行结果:
测试代码2:与测试代码1效果一样,不同点在于存放数据是在堆内存。
#include
#include //calloc()
#include //memset()
#define SIZE 5
typedef struct s_queue
{
int *data;
int front; //队首
int rear; //队尾
}Queue;
/*函数声明*/
void init_queue(Queue *queue);
int is_empty(Queue *queue);
int push_queue(Queue *queue, int input);
int pop_queue(Queue *queue, int *output);
void display_queue(Queue *queue);
int main(int argc, char *argv[])
{
Queue queue;
init_queue(&queue);//初始化队列
int input, ret, output;
while(1)
{
scanf("%d", &input);
if( input > 0 )//进队
{
ret = push_queue(&queue, input);
if( ret == 0)
{
display_queue( &queue );//打印队列的所有元素
}
else
{
printf("push data to queue is failed\n");
}
}
else if( input < 0 )//出队
{
ret = pop_queue(&queue, &output);
if( ret == 0)
{
printf("出队的元素是[%d]\n", output);
display_queue( &queue );
}
else
{
printf("pop data from queue is failed\n");
}
}
else if(input == 0)//退出
{
break;
}
}
free(queue.data);//释放资源
return 0;
}
void init_queue(Queue *queue)//初始化队列
{
memset(queue, 0, sizeof(*queue));//清零
queue->data = (int*) calloc( SIZE, sizeof(int) );
queue->front = -1;
queue->rear = -1;
}
int is_empty(Queue *queue)//判断队列是否为空
{
return queue->front == queue->rear;
}
int is_full(Queue *queue)//判断队列是否满了
{
return queue->rear == (SIZE - 1);
}
int push_queue(Queue *queue, int input)//元素入队
{
if( is_full(queue) == 1 )
{
return -1;
}
queue->rear++;
queue->data[queue->rear] = input;
return 0;
}
int pop_queue(Queue *queue, int *output)//元素出队,出队的元素存放到output
{
if( is_empty(queue) == 1 )
{
return -1;
}
queue->front++;
*output = queue->data[queue->front];
return 0;
}
void display_queue(Queue *queue)//打印队列所有元素
{
if( is_empty(queue) == 1)
{
printf("the queue is empty\n");
return ;
}
printf("队首 ");
int i;
for(i=queue->front+1; i<=queue->rear; i++ )
{
printf("[%d] ", queue->data[i]);
}
printf("队尾\n");
}
2.2 循环顺序存储队列
为了有效利用内存空间,循环使用 出队元素 的空间。
例子:队的大小设置为5, 输入正数--〉入队,输入负数--〉出队, 输入0--〉退出
代码结构:
测试代码:
#include
#include //calloc()
#include //memset()
#define SIZE 5
typedef struct s_queue
{
int *data;
int front; //队首
int rear; //队尾
}Queue;
/*函数声明*/
void init_queue(Queue *queue);
int is_empty(Queue *queue);
int push_queue(Queue *queue, int input);
int pop_queue(Queue *queue, int *output);
void display_queue(Queue *queue);
int main(int argc, char *argv[])
{
Queue queue;
init_queue(&queue);//初始化队列
int input, ret, output;
while(1)
{
scanf("%d", &input);
if( input > 0 )//进队
{
ret = push_queue(&queue, input);
if( ret == 0)
{
display_queue( &queue );//打印队列的所有元素
}
else
{
printf("push data to queue is failed\n");
}
}
else if( input < 0 )//出队
{
ret = pop_queue(&queue, &output);
if( ret == 0)
{
printf("出队的元素是[%d]\n", output);
display_queue( &queue );
}
else
{
printf("pop data from queue is failed\n");
}
}
else if(input == 0)//退出
{
break;
}
}
free(queue.data);//释放资源
return 0;
}
void init_queue(Queue *queue)//初始化队列
{
memset(queue, 0, sizeof(*queue));//清零
queue->data = (int*) calloc( SIZE, sizeof(int) );
queue->front = 0;
queue->rear = 0;
}
int is_empty(Queue *queue)//判断队列是否为空
{
return queue->front == queue->rear;
}
int is_full(Queue *queue)//判断队列是否满了
{
return (queue->rear+1)%SIZE == queue->front;
}
int push_queue(Queue *queue, int input)//元素入队
{
if( is_full(queue) == 1 )
{
return -1;
}
queue->rear = (queue->rear+1)%SIZE;
queue->data[queue->rear] = input;
return 0;
}
int pop_queue(Queue *queue, int *output)//元素出队,出队的元素存放到output
{
if( is_empty(queue) == 1 )
{
return -1;
}
queue->front = (queue->front+1)%SIZE;
*output = queue->data[queue->front];
return 0;
}
void display_queue(Queue *queue)//打印队列所有元素
{
if( is_empty(queue) == 1)
{
printf("the queue is empty\n");
return ;
}
printf("队首 ");
int i;
for(i=queue->front+1; i %= SIZE, i!=queue->rear; i++ )
{
printf("[%d] ", queue->data[i]);
}
printf("[%d] 队尾\n", queue->data[i]);
}
运行结果:
三、链式存储队列
每个元素都存放在堆空间,并且地址一般是随机,不相邻的。 (用到才申请堆空间)
因为在对空间存放数据,所以一般不存在队满的情况。
例子:输入正数--〉入队,输入负数--〉出队, 输入0--〉退出
代码结构:
测试代码:
#include
#include //malloc()
typedef struct s_node
{
int data;
struct s_node *next;
}Node;
typedef struct s_queue
{
Node *front;
Node *rear;
}Queue;
/*函数声明*/
void init_queue(Queue *queue);
int is_empty(Queue *queue);
int push_queue(Queue *queue, int input);
int pop_queue(Queue *queue, int *output);
void display_queue(Queue *queue);
void free_queue(Queue *queue);
int main(int argc, char *argv[])
{
Queue queue;
init_queue(&queue);//初始化队列
int input, ret, output;
while(1)
{
scanf("%d", &input);
if( input > 0 )//进队
{
ret = push_queue(&queue, input);
if( ret == 0)
{
display_queue( &queue );//打印队列的所有元素
}
else
{
printf("push data to queue is failed\n");
}
}
else if( input < 0 )//出队
{
ret = pop_queue(&queue, &output);
if( ret == 0)
{
printf("出队的元素是[%d]\n", output);
display_queue( &queue );
}
else
{
printf("pop data from queue is failed\n");
}
}
else if(input == 0)//退出
{
break;
}
}
free_queue(&queue);//释放资源
return 0;
}
void init_queue(Queue *queue)//初始化队列
{
queue->front = NULL;
queue->rear = NULL;
}
int is_empty(Queue *queue)//判断队列是否为空
{
return queue->rear == NULL;
}
int push_queue(Queue *queue, int input)//元素入队
{
Node *new_node;
new_node = (Node*) malloc( sizeof(Node));
new_node->data = input;
new_node->next = NULL;
if(queue->rear == NULL)//链队为空 ,新节点既是队首节点也是队尾节点。
{
queue->front = new_node;
queue->rear = new_node;
}
else //链队不为空,新的节点成为队尾,
{
queue->rear->next = new_node;
queue->rear = new_node;
}
return 0;
}
int pop_queue(Queue *queue, int *output)//元素出队,出队的元素存放到output
{
if( is_empty(queue) == 1 )
{
return -1;
}
Node *tmp = queue->front;//tmp用来指向第一个数据节点,然后释放节点
if(queue->front == queue->rear)//链队只有一个数据节点
{
queue->front = NULL;
queue->rear = NULL;
}
else //链队有多个数据节点
{
queue->front = queue->front->next;
}
*output = tmp->data;
free(tmp);//释放节点空间
return 0;
}
void display_queue(Queue *queue)//打印队列所有元素
{
if( is_empty(queue) == 1)
{
printf("the queue is empty\n");
return ;
}
printf("队首 ");
Node *tmp;
for(tmp=queue->front; tmp != NULL; tmp = tmp->next )
{
printf("[%d] ", tmp->data);
}
printf("\n");
}
void free_queue(Queue *queue)//释放链队
{
if( is_empty(queue) == 1)
{
return ;
}
Node *tmp;
for(tmp=queue->front; tmp != NULL; tmp = queue->front )
{
queue->front = queue->front->next;
printf("free: [%d] \n", tmp->data);
free(tmp);
}
}
运行结果: