wangqiuji

 

队列

队列:

只有两个口进出数据,一个专门进入数据,另一个专门出数据,先进先出,FIFO表

1. 顺序队列:

数据项 :

存储元素的连续内存的首地址

容量

队头位置    (出队)

队尾位置    (入队)

[元素数量]

运算:创建、销毁、清空、出队、入队、队空、队满、队头、队尾、元素数量

需要注意的问题

1、存储元素是由一维数组+队头位置front+队尾位置rear来表示,入队rear+1,出队front+1,为了让队列能够反复使用,我们需要把一维数组想象成一个环,因此+1后都需要对容量cal求余

front = (front+1)%cal

rear = (rear+1)%cal

2、判断队空和队满问题

如果不处理该问题,那么队空和队满的条件都是 front==rear,就无法区分是队空还是队满

方法1:存储元素的内存多增加一个位置空间(常考)

队空:front==rear

队满:(rear+1)%cal == front

代价:需要额外申请存储一个元素的内存

计算数量:(rear-front+cal)%cal

队尾数据下标:(rear-1+cal)%cal

方法2:顺序队列结构中增加一个记录元素数量的数据项,通过数量与容量对比判断队空、队满

设计顺序队列
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int

//    顺序队列结构
typedef struct ArrayQueue
{
    TYPE* ptr;
    size_t cal;        //    容量
    size_t front;    //    队头位置head\begin
    size_t rear;    //    队尾位置tail\back
}ArrayQueue;

//    创建顺序队列
ArrayQueue* create_array_queue(size_t cal)
{
    //    申请队列结构内存
    ArrayQueue* queue = malloc(sizeof(ArrayQueue));
    //    申请存储队列元素的内存
    queue->ptr = malloc(sizeof(TYPE)*(cal+1));
    //    初始化容量
    queue->cal = cal+1;

    queue->front = 0;
    queue->rear = 0;

    return queue;
}

//    销毁
void destroy_array_queue(ArrayQueue* queue)
{
    free(queue->ptr);
    free(queue);
}
//    队空
bool empty_array_queue(ArrayQueue* queue)
{
    return queue->front == queue->rear;
}

//    队满
bool full_array_queue(ArrayQueue* queue)
{
    return (queue->rear+1)%queue->cal == queue->front;    
}

//    入队
bool push_array_queue(ArrayQueue* queue,TYPE data)
{
    if(full_array_queue(queue)) return false;

    queue->ptr[queue->rear] = data;
    queue->rear = (queue->rear+1)%queue->cal;
    return true;
}

//    出队
bool pop_array_queue(ArrayQueue* queue)
{
    if(empty_array_queue(queue)) return false;
    queue->front = (queue->front+1)%queue->cal;
    return true;
}

//    队头
TYPE head_array_queue(ArrayQueue* queue)
{
    return queue->ptr[queue->front];    
}

//    队尾
TYPE tail_array_queue(ArrayQueue* queue)
{
    return queue->ptr[(queue->rear - 1 + queue->cal)%queue->cal];    
}

//    数量
size_t size_array_queue(ArrayQueue* queue)
{
    return (queue->rear - queue->front + queue->cal)%queue->cal;
}

2.链式队列:

由若干个节点组成的队列结构,只能操作队头节点、队尾节点

链式队列结构

队头指针

队尾指针

节点数量

运算:创建、销毁、队空、入队、出队、队头、队尾、数量

设计链式队列
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int

//    节点结构
typedef struct Node
{
    TYPE data;
    struct Node* next;
}Node;

//    创建节点
Node* create_node(TYPE data)
{
    Node* node = malloc(sizeof(Node));
    node->data = data;
    node->next = NULL;
    return node;
}

//    设计链式队列结构
typedef struct ListQueue
{
    Node* head;    //    队头指针
    Node* tail;    //    队尾指针
    size_t cnt;    //    节点数量
}ListQueue;

//    创建队列
ListQueue* create_list_queue(void)
{
    ListQueue* queue = malloc(sizeof(ListQueue));
    queue->head = NULL;
    queue->tail = NULL;
    queue->cnt = 0;
    return queue;
}


//    队空
bool empty_list_queue(ListQueue* queue)
{
    return 0 == queue->cnt;
}

//    入队
void push_list_queue(ListQueue* queue,TYPE data)
{
    Node* node = create_node(data);
    if(0 == queue->cnt)
    {
        queue->head = node;
        queue->tail = node;
    }
    else
    {
        queue->tail->next = node;
        queue->tail = node;
    }
    queue->cnt++;
}

//    出队
bool pop_list_queue(ListQueue* queue)
{
    if(empty_list_queue(queue))     return false;
    Node* temp = queue->head;
    queue->head = temp->next;
    free(temp);
    queue->cnt--;
    if(0 == queue->cnt) queue->tail = NULL;
    return true;
}

//    队头
TYPE head_list_queue(ListQueue* queue)
{
    return queue->head->data;
}

//    队尾
TYPE tail_list_queue(ListQueue* queue)
{
    return queue->tail->data;
}

//    数量
size_t size_list_queue(ListQueue* queue)
{
    return queue->cnt;
}

//    销毁队列
void destroy_list_queue(ListQueue* queue)
{
    while(pop_list_queue(queue));
    free(queue);
}

3.队列的应用:

1、数据排队处理-消息排队

2、树的层序遍历

3、图的广度优先遍历BFS

4、封装线程池、数据池

4.常考的笔试题、面试题:(喜欢考)

请使用两个栈来模拟一个队列的出队、入队功能(栈结构的功能都已实现,可以直接使用)

typedef struct Queue
{
     ArrayStack* s1;
     ArrayStack* s2;
}Queue;

1、s1负责入队、s2负责出队

2、当s2为空s1非空时,出队时,从s1转移到s2,s1需要全部转移到s2

3、当s1、s2非空时,优先出s2,直到s2出完,可以继续从s1转移到s2继续出队,直到s1、s2都为空才队空。

4、s2空s1满时,入队时需要s1全部转移到s2,入s1

5、s1s2满不入队,s1满s2非空也不入队

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int

//	设计顺序栈结构
typedef struct ArrayStack
{
	TYPE* ptr;	
	size_t cal;		//	容量
	size_t top;		//	栈顶位置 指向即将要入栈的位置
}ArrayStack;

//	创建
ArrayStack* create_array_stack(size_t cal)
{
	//	为顺序栈结构分配内存
	ArrayStack* stack = malloc(sizeof(ArrayStack));
	//	为存储数据元素分配内存
	stack->ptr = malloc(sizeof(TYPE)*cal);
	stack->cal = cal;
	stack->top = 0;
	return stack;
}

//	销毁
void destroy_array_stack(ArrayStack* stack)
{
	free(stack->ptr);
	free(stack);
}

//	栈空
bool empty_array_stack(ArrayStack* stack)
{
	return !stack->top;	
}

//	栈满
bool full_array_stack(ArrayStack* stack)
{
	return stack->top >= stack->cal;
}

//	入栈
bool push_array_stack(ArrayStack* stack,TYPE data)
{
	if(full_array_stack(stack)) return false;
	stack->ptr[stack->top++] = data;
	return true;
}

//	出栈
bool pop_array_stack(ArrayStack* stack)
{
	if(empty_array_stack(stack)) return false;
	stack->top--;
	return true;
}

//	栈顶
bool top_array_stack(ArrayStack* stack,TYPE* data)
{
	if(empty_array_stack(stack)) return false;
	*data = stack->ptr[stack->top-1];
	return true;
}

//	数量
size_t size_array_stack(ArrayStack* stack)
{
	return stack->top;
}

posted on 2023-08-18 16:36  翻斗花园牛大爷!  阅读(16)  评论(0编辑  收藏  举报

导航