数据结构与算法 队列

数据结构与算法 队列

一、简述

       记--顺序存储队列、链式存储队列;其中顺序存储队列又分为循环队列和非循环队列。

       队列简称队,它是一种操作受限的线性表,其限制为仅允许在表的一端进行插入(插入的一端称为队首,front),在表的另一端进行删除(删除的一端称为队尾)。插入新的元素称为进队或入队,删除元素也称为出队或离队。由于队列的一端只能插入,另一端只能删除,每个元素必然按照进队的顺序排列(出队),所以又把队列称为先进先出表。

        

二、顺序存储队列

       2.1 非循环顺序存储队列

             例子:队的大小设置为5, 输入正数--〉入队,输入负数--〉出队, 输入0--〉退出

             代码结构:

                                    

             测试代码1:

#include <stdio.h>
#include <string.h> //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 <stdio.h>
#include <stdlib.h> //calloc()
#include <string.h> //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 <stdio.h>
#include <stdlib.h> //calloc()
#include <string.h> //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 <stdio.h>
#include <stdlib.h> //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);
	}
}

      运行结果:

                        

猜你喜欢

转载自blog.csdn.net/nanfeibuyi/article/details/81380732