• 数据结构之队列


    基本概念和性质

    • 先进先出:最后插入队列中的元素总是最后被删除;每次从队列中删除的总是最早插入的元素

    • 栈和队列的主要区别:插入、删除操作的限定不一样

    顺序队列

    顺序队列会产生“假溢出”的问题,即无法使用 Q.rear == Q.front 来区分队空和队满,因此引入循环队列

    • 判断队空队满
      1. 牺牲一个单元来判断
        1. 队满:(Q.rear + 1) % MaxSize == Q,front
        2. 队空: Q.rear == Q.front
        3. 队中元素的个数:(Q.rear - Q.front + MaxSize) % MaxSize
      2. 设置计数器
        1. 队满:Q.size == MaxSize
        2. 队空:Q.size == 0
        3. 队中元素的个数:Q.size
      3. 设置判断标志
        1. 队满:Q.flag == 0时,若执行入队操作导致 Q.rear == Q.front 则为队空
        2. 队空:Q.flag ==1时,若执行出队操作导致 Q.rear == Q.front 则为队空
    // 创建队列结构
    #define MaxSize 10
    
    typedef struct {
    	ElemType data[MaxSize]; // 数据
    	int front, rear; // 队头、队尾
    } SqQueue;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    // 初始化队列
    void InitQueue(SqQueue &Q){
    	Q.front = 0;
    	Q.rear = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    // 队列判空
    bool isEmpty(SqQueue Q) {
    	if(Q.front == Q.rear) 
    		return true;
    	else 
    		return false;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    // 入队
    bool EnQueue(SqQueue &Q, ElemType x) {
    	if((Q.rear + 1) % MaxSize == Q.front)	// 队满
    		return false; 
    	Q.data[Q.rear] = x;
    	Q.rear = (Q.rear + 1) % MaxSize;
    	return true;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    // 出队
    bool DeQueue(SqQueue &Q, ElemType &x) {
    	if(Q.rear == Q.front)	// 队空 
    		return false;
    	x = Q.data[Q.front];
    	Q.front = [Q.front + 1] % MaxSize;
    	return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    // test
    int main() {
    	SqQueue Q;
    	int x;
    	scanf("%d", &x);
    	InitQueue(Q);
    	EnQueue(Q, x);
    	DeQueue(Q, x);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    链式队列

    • 最适合做链队的链表是——带队首指针和队尾指针的非循环单链表

    • 最不适合做链队的链表是——只带队首指针的非循环双链表

    • 删除操作时——头尾指针都可能被修改(删除后队空时)

    // 创建队列结构
    typedef struct LinkNode{
    	ElemType data;
    	struct LinkNode *next;
    }LinkNode;
    
    typeof struct{
    	LinkNode *front, *rear;
    }LinkQueue;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    // 初始化
    void InitQueue(LinkQueue &Q) {
    	Q.front = (LinkNode *)malloc(sizeof(LinkNode));
    	Q.rear = Q.front;
    	Q.front -> next = NULL;
    }
    
    // 判空
    bool IsEmpty(LinkQueue Q) {
    	if(Q.front == Q.rear) return true;
    	else return false;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    void InQueue(LinkQueue &Q, ElemType x) {
    	// 新建结点,链式一般不考虑队满的情况
    	LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
    	s -> data = x;
    	s -> next = NULL;
    	Q.rear -> next = s;			// 插入队尾
    	Q.rear = s;					// 队尾指针指向队尾
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    bool DeQueue(LinkQueue &Q, ElemType &x) {
    	if(Q.front == Q.rear) return false; 	// 判空 也可以直接调用IsEmpty(Q)函数
    	LinkNode *p = Q.front -> next;			
    	x = p -> data;
    	Q.front -> next = p -> next;
    	if(Q.rear == p) 						// 出队后若为空队
    		Q.rear = Q.front;
    	free(p);								// 这个是一个经常会忘记的点,要把p释放了
    	
    	return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    双端队列

    这个代码实现可能会比较麻烦,But 只需要知道怎么操作就行了

    • 双端队列

    在这里插入图片描述

    • 输出受限的双端队列

    在这里插入图片描述

    • 输入受限的双端队列

    在这里插入图片描述

  • 相关阅读:
    孙卫琴的《精通Vue.js》读书笔记-Vue组件的命名规则
    jib插件打包docker镜像(IDEA)
    C语言动态内存管理
    【JVM】JVM实战笔记-随笔
    java中Date类之GMT、UTC
    C语言中文网 - Shell脚本 - 0
    uwsgi部署多进程django apscheduler与问题排查
    去除pdf/word的水印艺术字
    C++面向对象程序设计(第2版)第四章(对运算符进行重载)知识点总结
    使用zeek做HTTP RPC性能检测
  • 原文地址:https://blog.csdn.net/weixin_47547625/article/details/126082319