创建队列

创建顺序队列



/*  */
#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值