创建顺序队列
/* */
#include "stdio.h"
#define MAX 10
/* 利用数组创建顺序队列 sequential:顺序 */
typedef struct my_queue{
int data[MAX]; // 存放数据 data[0] -- data[9]
int front; // 队列头 -- 读取/删除
int rear; // 队列尾 -- 插入
}seq_queue,*seq_queue_p; // sequential_queue_p == struct my_queue *
/* 初始化队列:队列头=队列尾 */
static void init_queue( seq_queue *queue ) // 指针类参数在子函数中修改能影响到全局 -- 主函数中把结构体地址传进来
{
queue->front = queue->rear = 0; // 头和尾都指向data[0]
}
/* 插入数据:从尾巴插入,插入后rear移动到数组的下一位、即尾巴指向的永远都是空数组位 */
static int insert_queue( seq_queue *queue, int new_data )
{
// 先判断队列满了没有
if( queue->rear > MAX ){
printf(" the queue is overflow ");
return 0; // 队满,退出
}
else{
queue->data[queue->rear] = new_data; // 从rear处插入
queue->rear += 1; // rear 指向数组下一位;
return 1;
}
}
/* 读取数据/删除数据: 从队头开始删除,删除完后front指向数组下一位 */
static int read_queue( seq_queue *queue, int *front_data )
{
// 先判断队列空了没有
if( queue->front == queue->rear ){
printf("the queue is empty \n\r ");
return 0; // 队空,退出
}
else{
*front_data = queue->data[queue->front];
queue->front += 1;
return 1;
}
}
int main(int argc, char **argv)
{
seq_queue my_first_queue; // 结构体实化
int queue_data;
int flag;
init_queue(&my_first_queue);
insert_queue(&my_first_queue,1);
insert_queue(&my_first_queue,3);
insert_queue(&my_first_queue,5);
insert_queue(&my_first_queue,7);
read_queue(&my_first_queue,&queue_data);
// 读取所有的值
for(;;){
flag = read_queue(&my_first_queue,&queue_data);
if( flag == 0 )
break;
if( flag == 1 ){
printf("%d\n\r",queue_data);
}
}
return 0;
}
创建循环队列
要点:使用求余功能实现循环(求余符号 %)
/* */
#include "stdio.h"
#define MAX 10
/* 利用数组创建循环队列 circular:循环 */
typedef struct my_queue{
int data[MAX]; // 存放数据 data[0] -- data[9]
int front; // 队列头 -- 读取/删除
int rear; // 队列尾 -- 插入
}seq_queue,*seq_queue_p; // sequential_queue_p == struct my_queue *
/* 初始化队列:队列头=队列尾 */
static void init_queue( seq_queue *queue ) // 指针类参数在子函数中修改能影响到全局 -- 主函数中把结构体地址传进来
{
queue->front = queue->rear = 0; // 头和尾都指向data[0]
}
/* 插入数据:从尾巴插入,插入后rear= ( (rear+1)%MAX )*/
static int insert_queue( seq_queue *queue, int new_data )
{
// 先判断队列满了没有 (rear+1)%MAX == front 则表明队满
if( (queue->rear+1)%MAX == queue->front ){
printf(" the queue is overflow ");
return 0; // 队满退出
}
else{
queue->data[queue->rear] = new_data; // 从rear处插入
queue->rear = ( (queue->rear+1)%MAX ); // rear 指向数组下一位;
return 1;
}
}
/* 读取数据/删除数据: 从队头开始删除,front= ( (front+1)%MAX ) */
static int read_queue( seq_queue *queue, int *front_data )
{
// 先判断队列空了没有
if( queue->front == queue->rear ){
printf("the queue is empty \n\r ");
return 0; // 队空,退出
}
else{
*front_data = queue->data[queue->front];
queue->front = ( (queue->front+1)%MAX );
return 1;
}
}
int main(int argc, char **argv)
{
seq_queue my_first_queue; // 结构体实化
int queue_data;
int flag;
init_queue(&my_first_queue);
insert_queue(&my_first_queue,1);
insert_queue(&my_first_queue,3);
insert_queue(&my_first_queue,5);
insert_queue(&my_first_queue,7);
read_queue(&my_first_queue,&queue_data);
// 读取所有的值
for(;;){
flag = read_queue(&my_first_queue,&queue_data);
if( flag == 0 )
break;
if( flag == 1 ){
printf("%d\n\r",queue_data);
}
}
return 0;
}
链队列
思想:
有数据插入,则新创建一个新节点并分配内存,让rear指向新开辟的节点;front->next永远指向最老的节点。
本质:链队列的本质是创建了一个链表,然后创建front和rear两个特殊节点,最后编写程序实现先进先出功能
/* */
#include <stdio.h>
#include <stdlib.h>
/* 利用链表创建链队列
思想:有数据插入数据,新创建一个节点并分配内存,让rear指向新开辟的节点,front->next指向最老的节点
front->next永远指向最老的节点。
链队列的本质是创建了一个链表,然后创建front和rear两个特殊节点,然后编写程序实现先进先出 */
typedef struct my_list{
int data;
struct my_list *next; // 注意指针类型
}queuenode;
typedef struct my_queue{
queuenode *front; // 队列头节点 -- 使用指针的目的是后面会在子函数中对其进行修改
queuenode *rear; // 队列尾节点 --
}list_queue;
/* 初始化队列:队列头节点和队列尾节点都指向NULL */
// quequ在main函数中的定义:list_queue queue; 使用时将其地址传进来、注意不用分配内存,定义时自动分配内存了
// 如果在mian中定义为结构体指针:list_queue *queue; 那么要在这里分配内存,并且还要将queue输出返回到main中才可以。
static void init_queue(list_queue *queue)
{
// 给指针分配内存
queue->front = ( queuenode *)malloc( sizeof(queue->front) );
queue->rear = queue->front; // 两个指针变量的地址都是一样的,都指向同一块内存
queue->front = queue->rear; // 队列头节点 = 队列为节点
queue->front->next = queue->rear->next = NULL; // next指向0地址
}
/* 插入数据:从尾巴插入
注意:列表头节点是不存放数据的,从front-next开始存放数据 */
static int insert_queue( list_queue *queue ,int new_data)
{
queuenode *new_node;
new_node = ( queuenode *)malloc( sizeof(new_node) ); // 给结构体指针分配内存
new_node->data = new_data;
new_node->next = NULL; // 新插入数据的next指针指向NULL
queue->rear->next = new_node; // ①
queue->rear = new_node; // ②
// ①②句分析:插入第一个节点时,queue->rear和queue->front这两个指针变量的地址都是一样的
// 故执行①的结果是queue->front->next也指向了new_node
// 执行②后,queue->rear这个指针变量的地址变了,变成了new_node这个指针变量的地址,而queue->front这个指针变量的地址没有变化
// 所以插入第一个节点以后,queue->rear和queue->front两个指针变量的地址不再一样
// 执行插入节点时queue->front指针变量指向的地址不变,而queue->rear指针变量指向的地址不断的发生变化
}
/* 读取数据/删除数据:从front->next开始读 -- 执行删除操作最后记得释放内存
注:删除数据过程,front地址是不变的,变的是front->next */
static int read_queue( list_queue *queue, int *front_data)
{
queuenode *old_front; // 从front->next节点取出数据后,这个节点就变成老节点了,需要释放该节点的空间
// 先判断是否队空
if( queue->front == queue->rear ){
printf("the queue is empty \n\r ");
return 0; // 队空,退出
}
old_front = queue->front->next;
*front_data = queue->front->next->data; // 取出数据
queue->front->next = queue->front->next->next; // front->next指向old_front的下一个节点
free( old_front ); // 释放内存空间,如果old_front对应的是queue->rear这个节点,说明这是最后一个数据了
if( queue->front->next == NULL ){ // 如果已经将最后一个数据取完,则让front=rear
queue->front = queue->rear;
}
return 1;
}
int main(int argc, char **argv)
{
list_queue queue; // 成员函数都是指针,不用设置为 list_queue *queue
int data;
int flag;
init_queue(&queue);
insert_queue( &queue ,1);
insert_queue( &queue ,3);
insert_queue( &queue ,5);
insert_queue( &queue ,7);
read_queue( &queue, &data);
for(;;){
flag = read_queue( &queue, &data);
if( flag == 0 )
break;
if( flag == 1 )
printf("%d\n\r",data);
}
return 0;
}