探索数据结构:特殊的双向队列

✨✨ 欢迎大家来到贝蒂大讲堂✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:数据结构与算法
贝蒂的主页:Betty’s blog

1. 双向队列的定义

**双向队列(double‑ended queue)**是一种特殊的队列,它允许在队列的队尾与队头插入与删除元素。根据其定义,我们也可以理解为两个栈在栈底相连。

  1. 队尾入队

img

  1. 队首入队

img

  1. 队尾出队

img

  1. 队尾出队

img

2. 双向队列的分类

双向队列也是线性表的一种,所以也可以分别用链表数组实现。基于链表实现:为了方便双向队列在尾部的插入与删除操作,所以我们选用双向链表。基于数组实现:与队列实现类似,需要用循环数组(原因参考队列实现)。

img

3. 双向队列的功能

  1. 队列的初始化。
  2. 判断队列是否为空。。
  3. 返回队头与队尾的元素。
  4. 返回队列的大小。
  5. 入队与出队。
  6. 打印队列的元素。
  7. 销毁队列。

4. 双向队列的声明

4.1. 链式队

双向队列与普通队列的声明区别就在于双向队列是基于双向链表的方式实现。

typedef int QDataType;
typedef struct DuListNode
{QDataType data;struct Node* prev;struct Node* next;
}DuListNode;typedef struct Deque
{size_t size;DuListNode* front;DuListNode* rear;
}Deque;

4.2. 循环队

循环队列的实现方式与普通队列差不多。

typedef int QDataType;
#define MAXSIZE 50  //定义元素的最大个数
typedef struct {QDataType *data;int front;  //头指针int rear;   //尾指针
}Deque;

5. 队列的初始化

5.1. 链式队

void DequeInit(Deque* d)//初始化
{assert(d);d->front = NULL;d->rear = NULL;d->size = 0;
}

5.2. 循环队

void DequeInit(Deque* d)//初始化
{d->data = (QDataType*)malloc(sizeof(QDataType )* MAXSIZE);if (d->data == NULL){perror("malloc fail:");return;}d->front = 0;d->rear = 0;
}

5.3. 复杂度分析

  • 时间复杂度:无论是链式队还是循环队列花费时间都是一个常数,所以时间复杂度为O(1)。
  • 空间复杂度:链式队空间是一个固定大小,空间复杂度为O(1)。而需要开辟整个队列的大小,空间复杂度为O(N)。

6. 判断队列是否为空

6.1. 链式队

bool DequeEmpty(Deque* d)//判断是否为空
{assert(d);return (d->front == NULL) && (d->rear == NULL);
}

6.2. 循环队

bool DequeEmpty(Deque* d)//判断是否为空
{assert(d);return d->front == d->rear;
}

6.3. 复杂度分析

  • 时间复杂度:无论是链式队还是循环队列花费时间都是一个常数,所以时间复杂度为O(1)。
  • 空间复杂度:无论是链式队还是循环队列花费空间都是一个固定大小,所以空间复杂度为O(1)。

7. 判断队列是否为满

7.1. 链式队

链式队并不需要判断。

7.2. 循环队

为什么要取模操作,可以参考一下上一篇普通队列的实现,同下。

bool DequeFull(Deque* d)//判断队列是否满
{assert(d);return (d->rear + 1) % MAXSIZE == d->front;
}

8. 返回队头与队尾的元素

8.1. 链式队

QDataType DequeFront(Deque* d)//获取队头元素
{assert(d);assert(!DequeEmpty(d));return d->front->data;
}
QDataType DequeBack(Deque* d)//获取队尾元素
{assert(d);assert(!DequeEmpty(d));return d->rear->data;
}

8.2. 循环队

QDataType DequeFront(Deque* d)//获取队头元素
{assert(d);assert(!DequeEmpty(d));return d->data[d->front];
}
QDataType DequeBack(Deque* d)//获取队尾元素
{assert(d);assert(!DequeEmpty(d));return d->data[(d->rear-1+MAXSIZE)%MAXSIZE];
}

8.3. 复杂度分析

  • 时间复杂度:无论是链式队还是循环队列花费时间都是一个常数,所以时间复杂度为O(1)。
  • 空间复杂度:无论是链式队还是循环队列花费空间都是一个固定大小,所以空间复杂度为O(1)

9. 返回队列的大小

9.1. 链式队

size_t DequeSize(Deque* d)//队列长度
{return d->size;
}

9.2. 循环队

size_t DequeSize(Deque* d)//获取队列长度
{assert(d);return (d->rear - d->front + MAXSIZE) % MAXSIZE;
}

9.3. 复杂度分析

  • 时间复杂度:无论是链式队还是循环队列花费时间都是一个常数,所以时间复杂度为O(1)。
  • 空间复杂度:无论是链式队还是循环队列花费空间都是一个固定大小,所以空间复杂度为O(1)

10. 入队

10.1. 链式队

10.1.1. 队头入队
void DequeFrontPush(Deque* d, QDataType x)//队首入队
{assert(d);DuListNode* newnode = (DuListNode*)malloc(sizeof(DuListNode));if (newnode == NULL){perror("malloc fail");return;}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;if (d->front == NULL){d->front = d->rear = newnode;}else{d->front->prev = newnode;newnode->next = d->front;d->front = newnode;}d->size++;
}
10.1.2. 队尾入队
void DequeRearPush(Deque* d, QDataType x)//队尾入队
{assert(d);DuListNode* newnode = (DuListNode*)malloc(sizeof(DuListNode));if (newnode == NULL){perror("malloc fail");return;}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;if (d->front == NULL){d->front = d->rear = newnode;}else{d->rear->next = newnode;newnode->prev = d->rear;d->rear = newnode;}d->size++;
}

10.2. 循环队

入队需要提前判断队列是否为满。

10.2.1. 队头入队
void DequeFrontPush(Deque* d, QDataType x)//队首入队
{assert(d);if (DequeFull(d)){printf("队列已满\n");return;}d->data[(d->front - 1 + MAXSIZE) % MAXSIZE]=x;d->front = (d->front - 1 + MAXSIZE) % MAXSIZE;
}
10.2.2. 队尾入队
void DequeRearPush(Deque* d, QDataType x)//队尾入队
{assert(d);if (DequeFull(d)){printf("队列已满\n");return;}d->data[d->rear] = x;d->rear = (d->rear + 1) % MAXSIZE;
}

10.3. 复杂度分析

  • 时间复杂度:无论是链式队还是循环队列花费时间都是一个常数,所以时间复杂度为O(1)。
  • 空间复杂度:无论是链式队还是循环队列花费空间都是一个固定大小,所以空间复杂度为O(1)

11. 出队

11.1. 链式队

出队需要提前判断队列是否为空。

11.1.1. 队头出队
void DequeFrontPop(Deque* d)//队首出队
{assert(d);assert(!DequeEmpty(d));//1.只有一个结点if (d->front == d->rear){free(d->front);d->front = d->rear = NULL;}//2.有多个结点else{DuListNode* next = d->front->next;next->prev = NULL;d->front->next = NULL;free(d->front);d->front = next;}d->size--;
}
11.1.2. 队尾出队
void DequeRearPop(Deque* d)//队尾出队
{assert(d);assert(!DequeEmpty(d));//1.只有一个结点if (d->front == d->rear){free(d->front);d->front = d->rear = NULL;}else{DuListNode* prev = d->rear->prev;prev->next = NULL;d->rear->prev = NULL;free(d->rear);d->rear = prev;}d->size--;
}

11.2. 循环队

11.2.1. 队头出队
void DequeFrontPop(Deque* d)//队首出队
{assert(d);assert(!DequeEmpty(d));d->front = (d->front + 1) % MAXSIZE;
}
11.2.2. 队尾出队
void DequeRearPop(Deque* d)//队尾出队
{assert(d);assert(!DequeEmpty(d));d->rear = (d->rear - 1+MAXSIZE) % MAXSIZE;
}

11.3. 复杂度分析

  • 时间复杂度:无论是链式队还是循环队列花费时间都是一个常数,所以时间复杂度为O(1)。
  • 空间复杂度:无论是链式队还是循环队列花费空间都是一个固定大小,所以空间复杂度为O(1)

12. 打印队列元素

12.1. 链式队

void DequePrint(Deque* d)//打印队列元素
{assert(d);DuListNode* cur = d->front;DuListNode* tail = d->rear;printf("队头:");while (cur != tail->next){printf("%d<=>", cur->data);cur = cur->next;}printf("队尾\n");
}

12.2. 循环队

void DequePrint(Deque* d)//打印队列元素
{assert(d);int cur = d->front;printf("队头->");while (cur != d->rear){printf("%d->", d->data[cur]);cur = (cur + 1) % MAXSIZE;}printf("队尾\n");}

12.3. 复杂度分析

  • 时间复杂度:无论是链式队还是循环队列都需要遍历这个队列,所以时间复杂度为O(N)。
  • 空间复杂度:无论是链式队还是循环队列花费空间都是一个固定大小,所以空间复杂度为O(1)

13. 销毁队列

13.1. 链式队

void DequeDestroy(Deque* d)//销毁队列
{assert(d);DuListNode* cur = d->front;while (cur){DuListNode* del = cur;cur = cur->next;free(del);del = NULL;}d->front = d->rear = NULL;
}

13.2. 循环队

void DequeDestroy(Deque* d)//销毁队列
{assert(d);free(d->data);d->data = NULL;d->front = d->rear = 0;
}

13.3. 复杂度分析

  • 时间复杂度:无论是链式队还是循环队列花费时间都是一个常数,所以时间复杂度为O(1)。
  • 空间复杂度:无论是链式队还是循环队列花费空间都是一个固定大小,所以空间复杂度为O(1)

14. 对比与应用

14.1. 对比

双向队列的两种实现方式的效果与普通队列实现差不多,这里就不在一一赘述。

14.2. 应用

双向队列兼备队列与栈的性质,所以可以应用于这两种数据结构的所有应用场景。

此外它应用于撤销的一种情景:通常情况下,撤销是以栈的方式实现,当我们每次更改时就入栈,撤销就出栈。但是我们知道系统给与栈的空间是有限的,我们不可能一直入栈。当入栈超过一个限度时,我们就用过删除栈底的数据,这时栈这个数据结构就无法满足需求。所以这时我们可以使用双向队列来实现。

15. 完整代码

15.1. 链式队

15.1.1. Deque.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int QDataType;
typedef struct DuListNode
{QDataType data;struct Node* prev;struct Node* next;
}DuListNode;typedef struct Deque
{size_t size;DuListNode* front;DuListNode* rear;
}Deque;
void DequeInit(Deque* d);//初始化
bool DequeEmpty(Deque* d);//判断是否为空
QDataType DequeFront(Deque* d);//获取队头元素
QDataType DequeBack(Deque* d);//获取队尾元素
size_t DequeSize(Deque* d);//获取队列长度
void DequeFrontPush(Deque* d, QDataType x);//队首入队
void DequeRearPush(Deque* d, QDataType x);//队尾入队
void DequeFrontPop(Deque* d);//队首出队
void DequeRearPop(Deque* d);//队尾出队
void DequePrint(Deque* d);//打印队列元素
void DequeDestroy(Deque* d);//销毁队列
15.1.2. Deque.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Deque.h"
void DequeInit(Deque* d)//初始化
{assert(d);d->front = NULL;d->rear = NULL;d->size = 0;
}
bool DequeEmpty(Deque* d)//判断是否为空
{assert(d);return (d->front == NULL) && (d->rear == NULL);
}
QDataType DequeFront(Deque* d)//获取队头元素
{assert(d);assert(!DequeEmpty(d));return d->front->data;
}
QDataType DequeBack(Deque* d)//获取队尾元素
{assert(d);assert(!DequeEmpty(d));return d->rear->data;
}
size_t DequeSize(Deque* d)//队列长度
{return d->size;
}
void DequeFrontPush(Deque* d, QDataType x)//队首入队
{assert(d);DuListNode* newnode = (DuListNode*)malloc(sizeof(DuListNode));if (newnode == NULL){perror("malloc fail");return;}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;if (d->front == NULL){d->front = d->rear = newnode;}else{d->front->prev = newnode;newnode->next = d->front;d->front = newnode;}d->size++;
}
void DequeRearPush(Deque* d, QDataType x)//队尾入队
{assert(d);DuListNode* newnode = (DuListNode*)malloc(sizeof(DuListNode));if (newnode == NULL){perror("malloc fail");return;}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;if (d->front == NULL){d->front = d->rear = newnode;}else{d->rear->next = newnode;newnode->prev = d->rear;d->rear = newnode;}d->size++;
}
void DequeFrontPop(Deque* d)//队首出队
{assert(d);assert(!DequeEmpty(d));//1.只有一个结点if (d->front == d->rear){free(d->front);d->front = d->rear = NULL;}//2.有多个结点else{DuListNode* next = d->front->next;next->prev = NULL;d->front->next = NULL;free(d->front);d->front = next;}d->size--;
}
void DequeRearPop(Deque* d)//队尾出队
{assert(d);assert(!DequeEmpty(d));//1.只有一个结点if (d->front == d->rear){free(d->front);d->front = d->rear = NULL;}else{DuListNode* prev = d->rear->prev;prev->next = NULL;d->rear->prev = NULL;free(d->rear);d->rear = prev;}d->size--;
}
void DequePrint(Deque* d)//打印队列元素
{assert(d);DuListNode* cur = d->front;DuListNode* tail = d->rear;printf("队头:");while (cur != tail->next){printf("%d<=>", cur->data);cur = cur->next;}printf("队尾\n");
}
void DequeDestroy(Deque* d)//销毁队列
{assert(d);DuListNode* cur = d->front;while (cur){DuListNode* del = cur;cur = cur->next;free(del);del = NULL;}d->front = d->rear = NULL;
}

15.2. 循环队

15.2.1. Deque.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int QDataType;
#define MAXSIZE 50  //定义元素的最大个数
typedef struct {QDataType *data;int front;  //头指针int rear;   //尾指针
}Deque;void DequeInit(Deque* d);//初始化
bool DequeEmpty(Deque* d);//判断是否为空
bool DequeFull(Deque* d);//判断队列是否满
QDataType DequeFront(Deque* d);//获取队头元素
QDataType DequeBack(Deque* d);//获取队尾元素
size_t DequeSize(Deque* d);//获取队列长度
void DequeFrontPush(Deque* d, QDataType x);//队首入队
void DequeRearPush(Deque* d, QDataType x);//队尾入队
void DequeFrontPop(Deque* d);//队首出队
void DequeRearPop(Deque* d);//队尾出队
void DequePrint(Deque* d);//打印队列元素
void DequeDestroy(Deque* d);//销毁队列
15.2.2. Deque.c
void DequeInit(Deque* d)//初始化
{d->data = (QDataType*)malloc(sizeof(QDataType )* MAXSIZE);if (d->data == NULL){perror("malloc fail:");return;}d->front = 0;d->rear = 0;
}
bool DequeEmpty(Deque* d)//判断是否为空
{assert(d);return d->front == d->rear;
}
bool DequeFull(Deque* d)//判断队列是否满
{assert(d);return (d->rear + 1) % MAXSIZE == d->front;
}
QDataType DequeFront(Deque* d)//获取队头元素
{assert(d);assert(!DequeEmpty(d));return d->data[d->front];
}
QDataType DequeBack(Deque* d)//获取队尾元素
{assert(d);assert(!DequeEmpty(d));return d->data[(d->rear-1+MAXSIZE)%MAXSIZE];
}
size_t DequeSize(Deque* d)//获取队列长度
{assert(d);return (d->rear - d->front + MAXSIZE) % MAXSIZE;
}
void DequeFrontPush(Deque* d, QDataType x)//队首入队
{assert(d);if (DequeFull(d)){printf("队列已满\n");return;}d->data[(d->front - 1 + MAXSIZE) % MAXSIZE]=x;d->front = (d->front - 1 + MAXSIZE) % MAXSIZE;
}
void DequeRearPush(Deque* d, QDataType x)//队尾入队
{assert(d);if (DequeFull(d)){printf("队列已满\n");return;}d->data[d->rear] = x;d->rear = (d->rear + 1) % MAXSIZE;
}
void DequeFrontPop(Deque* d)//队首出队
{assert(d);assert(!DequeEmpty(d));d->front = (d->front + 1) % MAXSIZE;
}
void DequeRearPop(Deque* d)//队尾出队
{assert(d);assert(!DequeEmpty(d));d->rear = (d->rear - 1+MAXSIZE) % MAXSIZE;
}
void DequePrint(Deque* d)//打印队列元素
{assert(d);int cur = d->front;printf("队头->");while (cur != d->rear){printf("%d->", d->data[cur]);cur = (cur + 1) % MAXSIZE;}printf("队尾\n");}
void DequeDestroy(Deque* d)//销毁队列
{assert(d);free(d->data);d->data = NULL;d->front = d->rear = 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/300228.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【并发编程系列】使用 CompletableFuture 实现并发任务处理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

python买铅笔 2024年3月青少年电子学会等级考试 中小学生python编程等级考试一级真题答案解析

目录 python买铅笔 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python买铅笔 2024年3月 python编程等级考试级编程题 一、题目要求 1、编…

Bigtable [OSDI‘06] 论文阅读笔记

原论文&#xff1a;Bigtable: A Distributed Storage System for Structured Data (OSDI’06) 1. Introduction Bigtable 是一种用于管理结构化数据的分布式存储系统&#xff0c;可扩展到非常大的规模&#xff1a;数千台服务器上的数据量可达 PB 级别&#xff0c;同时保证可靠…

《QT实用小工具·十七》密钥生成工具

1、概述 源码放在文章末尾 该项目主要用于生成密钥&#xff0c;下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #pragma execution_character_set("utf-8")#include "frmmain.h" #include "ui_frmmain.h" #include "qmessag…

js计算器实现

文章目录 1. 演示效果2. 分析思路3. 代码实现 1. 演示效果 2. 分析思路 给每个按钮添加点击事件&#xff0c;使用eval()进行计算。 3. 代码实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name&q…

低代码革新:软件开发的未来潜力与创新路径探索

过去的一年&#xff0c;挑战与机遇并存。人们一边忧虑市场经济下行所带来的新的增长难题、裁员危机&#xff0c;一边惊叹于AIGC、量子技术等领域不断涌现新的创新成果。 时代发生了改变&#xff0c;传统“互联网”的模式已走入尾声&#xff0c;新一轮的科技革命与产业变革正在到…

学习 MongoDB:打开强大的数据库技术大门

一、基本概念 MongoDB 是一个基于分布式文件存储的文档数据库&#xff0c;由 C 语言编写。它旨在为 Web 应用提供可扩展的高性能数据存储解决方案。 相信MySQL我们非常的熟悉&#xff0c;那么MySQL的表结构与MongoDB的文档结构进行类比的话可能更好理解MongoDB。 MySQL的数据…

Windows下Docker安装Kafka3+集群

编写 docker-compose.yaml 主要参照&#xff1a;https://www.cnblogs.com/wangguishe/p/17563274.html version: "3"services:kafka1:image: bitnami/kafka:3.4.1container_name: kafka1environment:- KAFKA_HEAP_OPTS-Xmx1024m -Xms1024m- KAFKA_ENABLE_KRAFTyes- K…

类和对象(上)

目录 类的定义&#xff1a; 类的访问限定符及封装&#xff1a; 访问限定符&#xff1a; 封装&#xff1a; 类的作用域&#xff1a; 类的实例化&#xff1a; ​编辑 类对象模型&#xff1a; 类对象的大小与存储方式&#xff1a; this指针&#xff1a; this指针的引出&…

《债务与国家的崛起》西方民主制度的金融起源 - 三余书屋 3ysw.net

债务与国家的崛起&#xff1a;西方民主制度的金融起源 你好&#xff0c;今天我们来聊聊由英国知名经济与金融历史学家詹姆斯麦克唐纳所著的《债务与国家的崛起》这本书。19世纪世界历史上发生了一次巨变&#xff0c;即“大分流”。当时西方通过工业革命实现了科技和经济的飞速…

vue项目入门——index.html和App.vue

vue项目中的index.html文件 在Vue项目中&#xff0c;index.html文件通常作为项目的入口文件&#xff0c;它包含了Vue应用程序的基础结构和配置。 该文件的主要作用是引入Vue框架和其他必要的库&#xff0c;以及定义Vue应用程序的启动配置。 import Vue from vue import App …

以动态库链接库 .dll 探索结构体参数

Dev c C语言实现第一个 dll 动态链接库 创建与调用-CSDN博客 在写dll 插件中发现的函数指针用途和 typedef 的定义指针的用法-CSDN博客 两步之后&#xff0c;尝试加入结构体实现整体数据使用。 注意结构体 Ak 是相同的 代码如下 DLL文件有两个&#xff0c;dll.dll是上面提到…

数据可视化高级技术Echarts(快速上手柱状图进阶操作)

目录 1.Echarts的配置 2.程序的编码 3.柱状图的实现&#xff08;入门实现&#xff09; 相关属性介绍&#xff08;进阶&#xff09;&#xff1a; 1.标记最大值/最小值 2.标记平均值 3.柱的宽度 4. 横向柱状图 5.colorBy series系列&#xff08;需要构造多组数据才能实现…

撸代码时,有哪些习惯一定要坚持?

我从2011年开始做单片机开发&#xff0c;一直保持以下撸代码的习惯。 1.做好代码版本管理 有些人&#xff0c;喜欢一个程序干到底&#xff0c;直到实现全部的产品功能&#xff0c;我以前做51单片机的项目就是这样。 如果功能比较多的产品&#xff0c;我不建议这样做&#xff0…

【Linux】指令

1. 简单指令 whoami 显示当前登入账号名 ls /home 现在有的用户名 adduser 用户名 新加用户&#xff08;必须在root目录下&#xff09; passwd 用户名 给这个用户设置密码 userdel -r 用户名 删除这个用户 pwd 显示当前所处路径 stat 文件名 / 文件夹名 显示文件状…

鸿蒙HarmonyOS 与 Android 的NDK有什么不一样?

1. 序言 就像开发Android要用Android Studio一样&#xff0c;Android Studio&#xff08;简称AS&#xff09;其实是基于IDEAgradle插件android插件开发而来。 鸿蒙系统&#xff0c;你可以认为它和android有点像&#xff0c;但又是超越android的存在&#xff0c;除了手机&…

《C语言深度解剖》(2):详解C语言分支语句和循环

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《C语言深度解剖》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多数据结构与算法点击专栏链接查看&am…

Java实现二叉树(上)

1.树型结构 1.1树型结构的概念 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因为它看 起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的 1.2树型结构的特点…

xshell7连接ubuntu18.04

&#x1f3a1;导航小助手&#x1f3a1; 1.查看ubuntu IP2.开启openssh-server3.静态IP设置4.Xshell连接 1.查看ubuntu IP 输入下面命令查看IP ifconfig -a可以看到网卡是ens33&#xff0c;IP为192.168.3.180。 2.开启openssh-server 1、执行下句&#xff0c;下载SSH服务 s…

openGauss学习笔记-257 openGauss性能调优-使用Plan Hint进行调优-Custom Plan和Generic Plan选择的Hint

文章目录 openGauss学习笔记-257 openGauss性能调优-使用Plan Hint进行调优-Custom Plan和Generic Plan选择的Hint257.1 功能描述257.2 语法格式257.3 示例 openGauss学习笔记-257 openGauss性能调优-使用Plan Hint进行调优-Custom Plan和Generic Plan选择的Hint 257.1 功能描…