当前位置: 首页 > news >正文

数据结构与算法-要点整理

知识导图:

请添加图片描述

一、数据结构

    包含:线性表(数组、队列、链表、栈)、散列表、树(二叉树、多路查找树)、图

1.线性表

    数据之间就是“一对一“的逻辑关系。
    线性表存储数据的实现方案有两种,分别是顺序存储结构链式存储结构
    包含:数组、队列、链表、栈。

1.1 数组:

    连续内存存储。简单,此处不多介绍。

1.2 队列:

可以通过数组+前后索引实现,也可以通过链表+前后指针实现。

queue:
1)通过数组+前后索引实现

#include <iostream>
#include <stdexcept>template <typename T, int capacity>
class Queue {
private:T arr[capacity];int front;  // 队头索引int rear;   // 队尾索引int size;   // 当前队列中的元素数量public:Queue() : front(0), rear(0), size(0) {}// 判断队列是否为空bool isEmpty() const {return size == 0;}// 判断队列是否已满bool isFull() const {return size == capacity;}// 入队操作void enqueue(const T& value) {if (isFull()) {throw std::overflow_error("Queue is full");}arr[rear] = value;rear = (rear + 1) % capacity;  // 循环更新队尾索引++size;}// 出队操作T dequeue() {if (isEmpty()) {throw std::underflow_error("Queue is empty");}T value = arr[front];front = (front + 1) % capacity;  // 循环更新队头索引--size;return value;}// 获取队头元素T getFront() const {if (isEmpty()) {throw std::underflow_error("Queue is empty");}return arr[front];}// 获取队列中的元素数量int getSize() const {return size;}
};int main() {Queue<int, 5> queue;try {// 入队操作queue.enqueue(1);queue.enqueue(2);queue.enqueue(3);// 输出队头元素std::cout << "Front element: " << queue.getFront() << std::endl;// 出队操作std::cout << "Dequeued element: " << queue.dequeue() << std::endl;// 再次输出队头元素std::cout << "Front element after dequeue: " << queue.getFront() << std::endl;// 输出队列中的元素数量std::cout << "Queue size: " << queue.getSize() << std::endl;} catch (const std::exception& e) {std::cerr << "Exception: " << e.what() << std::endl;}return 0;
}

2)通过链表+前后指针实现

#include <iostream>
#include <stdexcept>// 定义链表节点结构体
template <typename T>
struct Node {T data;Node<T>* next;Node(const T& value) : data(value), next(nullptr) {}
};// 定义队列类
template <typename T>
class Queue {
private:Node<T>* front;  // 队头指针Node<T>* rear;   // 队尾指针int size;        // 当前队列中的元素数量public:// 构造函数Queue() : front(nullptr), rear(nullptr), size(0) {}// 析构函数~Queue() {while (!isEmpty()) {dequeue();}}// 判断队列是否为空bool isEmpty() const {return size == 0;}// 获取队列中的元素数量int getSize() const {return size;}// 入队操作void enqueue(const T& value) {Node<T>* newNode = new Node<T>(value);if (isEmpty()) {front = rear = newNode;} else {rear->next = newNode;rear = newNode;}++size;}// 出队操作T dequeue() {if (isEmpty()) {throw std::underflow_error("Queue is empty");}T value = front->data;Node<T>* temp = front;front = front->next;if (front == nullptr) {rear = nullptr;}delete temp;--size;return value;}// 获取队头元素T getFront() const {if (isEmpty()) {throw std::underflow_error("Queue is empty");}return front->data;}
};int main() {Queue<int> queue;try {// 入队操作queue.enqueue(1);queue.enqueue(2);queue.enqueue(3);// 输出队头元素std::cout << "Front element: " << queue.getFront() << std::endl;// 出队操作std::cout << "Dequeued element: " << queue.dequeue() << std::endl;// 再次输出队头元素std::cout << "Front element after dequeue: " << queue.getFront() << std::endl;// 输出队列中的元素数量std::cout << "Queue size: " << queue.getSize() << std::endl;} catch (const std::exception& e) {std::cerr << "Exception: " << e.what() << std::endl;}return 0;
}

双端队列Deque:
    允许你从队列的两端进行元素的插入和删除操作,既可以在头部进行操作,也可以在尾部进行操作。

1)通过数组+前后索引实现

#include <iostream>
#include <stdexcept>template <typename T, int capacity>
class ArrayDeque {
private:T arr[capacity];int front;int rear;int size;public:ArrayDeque() : front(0), rear(0), size(0) {}// 判断队列是否为空bool isEmpty() const {return size == 0;}// 判断队列是否已满bool isFull() const {return size == capacity;}// 在队头插入元素void insertFront(const T& value) {if (isFull()) {throw std::overflow_error("Deque is full");}front = (front - 1 + capacity) % capacity;arr[front] = value;++size;}// 在队尾插入元素void insertRear(const T& value) {if (isFull()) {throw std::overflow_error("Deque is full");}arr[rear] = value;rear = (rear + 1) % capacity;++size;}// 从队头删除元素T deleteFront() {if (isEmpty()) {throw std::underflow_error("Deque is empty");}T value = arr[front];front = (front + 1) % capacity;--size;return value;}// 从队尾删除元素T deleteRear() {if (isEmpty()) {throw std::underflow_error("Deque is empty");}rear = (rear - 1 + capacity) % capacity;T value = arr[rear];--size;return value;}// 获取队头元素T getFront() const {if (isEmpty()) {throw std::underflow_error("Deque is empty");}return arr[front];}// 获取队尾元素T getRear() const {if (isEmpty()) {throw std::underflow_error("Deque is empty");}return arr[(rear - 1 + capacity) % capacity];}// 获取队列中的元素数量int getSize() const {return size;}
};int main() {ArrayDeque<int, 5> deque;try {deque.insertFront(1);deque.insertRear(2);std::cout << "Front element: " << deque.getFront() << std::endl;std::cout << "Rear element: " << deque.getRear() << std::endl;deque.deleteFront();std::cout << "Front element after deleteFront: " << deque.getFront() << std::endl;deque.deleteRear();std::cout << "Is deque empty after deletions? " << (deque.isEmpty() ? "Yes" : "No") << std::endl;} catch (const std::exception& e) {std::cerr << "Exception: " << e.what() << std::endl;}return 0;
}

2)通过链表+前后指针实现

#include <iostream>
#include <stdexcept>// 定义链表节点结构体
template <typename T>
struct Node {T data;Node<T>* prev;Node<T>* next;Node(const T& value) : data(value), prev(nullptr), next(nullptr) {}
};template <typename T>
class LinkedDeque {
private:Node<T>* front;Node<T>* rear;int size;public:LinkedDeque() : front(nullptr), rear(nullptr), size(0) {}~LinkedDeque() {while (!isEmpty()) {deleteFront();}}// 判断队列是否为空bool isEmpty() const {return size == 0;}// 在队头插入元素void insertFront(const T& value) {Node<T>* newNode = new Node<T>(value);if (isEmpty()) {front = rear = newNode;} else {newNode->next = front;front->prev = newNode;front = newNode;}++size;}// 在队尾插入元素void insertRear(const T& value) {Node<T>* newNode = new Node<T>(value);if (isEmpty()) {front = rear = newNode;} else {newNode->prev = rear;rear->next = newNode;rear = newNode;}++size;}// 从队头删除元素T deleteFront() {if (isEmpty()) {throw std::underflow_error("Deque is empty");}T value = front->data;Node<T>* temp = front;front = front->next;if (front == nullptr) {rear = nullptr;} else {front->prev = nullptr;}delete temp;--size;return value;}// 从队尾删除元素T deleteRear() {if (isEmpty()) {throw std::underflow_error("Deque is empty");}T value = rear->data;Node<T>* temp = rear;rear = rear->prev;if (rear == nullptr) {front = nullptr;} else {rear->next = nullptr;}delete temp;--size;return value;}// 获取队头元素T getFront() const {if (isEmpty()) {throw std::underflow_error("Deque is empty");}return front->data;}// 获取队尾元素T getRear() const {if (isEmpty()) {throw std::underflow_error("Deque is empty");}return rear->data;}// 获取队列中的元素数量int getSize() const {return size;}
};int main() {LinkedDeque<int> deque;try {deque.insertFront(1);deque.insertRear(2);std::cout << "Front element: " << deque.getFront() << std::endl;std::cout << "Rear element: " << deque.getRear() << std::endl;deque.deleteFront();std::cout << "Front element after deleteFront: " << deque.getFront() << std::endl;deque.deleteRear();std::cout << "Is deque empty after deletions? " << (deque.isEmpty() ? "Yes" : "No") << std::endl;} catch (const std::exception& e) {std::cerr << "Exception: " << e.what() << std::endl;}return 0;
}
1.3 链表:

    和顺序表不同,使用链表存储数据,不强制要求数据在内存中集中存储,各个元素可以分散存储在内存中。链表存储数据间逻辑关系的实现方案是:为每一个元素配置一个指针,每个元素的指针都指向自己的直接后继元素。

单向链表:
在这里插入图片描述

#include <iostream>struct ListNode {int val;ListNode* next;ListNode(int x) : val(x), next(nullptr) {}
};class LinkedList {
private:ListNode* head;public:LinkedList() : head(nullptr) {}void insertAtHead(int val) {ListNode* newNode = new ListNode(val);newNode->next = head;head = newNode;}void insertAtTail(int val) {ListNode* newNode = new ListNode(val);if (head == nullptr) {head = newNode;return;}ListNode* curr = head;while (curr->next!= nullptr) {curr = curr->next;}curr->next = newNode;}void deleteAtHead() {if (head == nullptr) {std::cout << "链表为空,无法删除" << std::endl;return;}ListNode* temp = head;head = head->next;delete temp;}void deleteAtTail() {if (head == nullptr) {std::cout << "链表为空,无法删除" << std::endl;return;}if (head->next == nullptr) {delete head;head = nullptr;return;}ListNode* curr = head;while (curr->next->next!= nullptr) {curr = curr->next;}delete curr->next;curr->next = nullptr;}void printList() {ListNode* curr = head;while (curr!= nullptr) {std::cout << curr->val << " ";curr = curr->next;}std::cout << std::endl;}// 查找元素是否存在bool search(int val) {ListNode* curr = head;while (curr!= nullptr) {if (curr->val == val) {return true;}curr = curr->next;}return false;}
};int main() {LinkedList list;list.insertAtHead(3);list.insertAtHead(2);list.insertAtHead(1);std::cout << "插入头部后的链表: ";list.printList();list.insertAtTail(4);list.insertAtTail(5);std::cout << "插入尾部后的链表: ";list.printList();list.deleteAtHead();std::cout << "删除头部节点后的链表: ";list.printList();list.deleteAtTail();std::cout << "删除尾部节点后的链表: ";list.printList();if (list.search(3)) {std::cout << "元素 3 存在于链表中" << std::endl;} else {std::cout << "元素 3 不存在于链表中" << std::endl;}return 0;
}

双向链表:

    “双向”指的是各节点之间的逻辑关系是双向的,头指针通常只设置一个。
在这里插入图片描述

#include <iostream>// 定义双向链表节点结构体
struct ListNode {int val;ListNode* prev;ListNode* next;ListNode(int x) : val(x), prev(nullptr), next(nullptr) {}
};// 双向链表类
class DoublyLinkedList {
private:ListNode* head;ListNode* tail;public:DoublyLinkedList() : head(nullptr), tail(nullptr) {}// 插入节点到链表头部void insertAtHead(int val) {ListNode* newNode = new ListNode(val);if (head == nullptr) {head = newNode;tail = newNode;} else {newNode->next = head;head->prev = newNode;head = newNode;}}// 插入节点到链表尾部void insertAtTail(int val) {ListNode* newNode = new ListNode(val);if (tail == nullptr) {head = newNode;tail = newNode;} else {newNode->prev = tail;tail->next = newNode;tail = newNode;}}// 删除头部节点void deleteAtHead() {if (head == nullptr) {std::cout << "链表为空,无法删除" << std::endl;return;}ListNode* temp = head;if (head == tail) {head = nullptr;tail = nullptr;} else {head = head->next;head->prev = nullptr;}delete temp;}// 删除尾部节点void deleteAtTail() {if (tail == nullptr) {std::cout << "链表为空,无法删除" << std::endl;return;}ListNode* temp = tail;if (head == tail) {head = nullptr;tail = nullptr;} else {tail = tail->prev;tail->next = nullptr;}delete temp;}// 打印链表元素(从头到尾)void printList() {ListNode* curr = head;while (curr!= nullptr) {std::cout << curr->val << " ";curr = curr->next;}std::cout << std::endl;}// 打印链表元素(从尾到头)void printListReverse() {ListNode* curr = tail;while (curr!= nullptr) {std::cout << curr->val << " ";curr = curr->prev;}std::cout << std::endl;}
};int main() {DoublyLinkedList list;list.insertAtHead(3);list.insertAtHead(2);list.insertAtHead(1);std::cout << "插入头部后的链表: ";list.printList();list.insertAtTail(4);list.insertAtTail(5);std::cout << "插入尾部后的链表: ";list.printList();list.deleteAtHead();std::cout << "删除头部节点后的链表: ";list.printList();list.deleteAtTail();std::cout << "删除尾部节点后的链表: ";list.printList();std::cout << "从尾到头打印链表: ";list.printListReverse();return 0;
}

单向循环链表与双向循环链表:
    单链表通过首尾连接可以构成单向循环链表:
在这里插入图片描述
    双向链表也可以进行首尾连接,构成双向循环链表:
在这里插入图片描述

静态链表:
    用静态链表存储数据,数据全部存储在数组中(和顺序表一样),但存储位置是随机的,数据之间"一对一"的逻辑关系通过一个整形变量(称为"游标",和指针功能类似)维持(和链表类似)。
在静态链表中,数组的每个元素代表一个链表节点,每个节点通常包含两部分:

  1. 数据域:存储节点的数据。
  2. 游标域(或指针域):存储下一个节点在数组中的索引,而不是像动态链表那样存储一个物理地址。

在这里插入图片描述

1.4 栈

    栈是一种后进先出的数据结构。

#include <iostream>
#include <vector>class ArrayStack {
private:std::vector<int> data;  // 存储元素的数组
public:// 入栈操作void push(int value) {
//使用 data.push_back(value) 将元素添加到 data 的末尾,实现入栈操作。data.push_back(value);}// 出栈操作int pop() {if (isEmpty()) {throw s

相关文章:

数据结构与算法-要点整理

知识导图: 一、数据结构 包含:线性表(数组、队列、链表、栈)、散列表、树(二叉树、多路查找树)、图 1.线性表 数据之间就是“一对一“的逻辑关系。 线性表存储数据的实现方案有两种,分别是顺序存储结构和链式存储结构。 包含:数组、队列、链表、栈。 1.1 数组…...

Fort Firewall:全方位守护网络安全

Fort Firewall是一款专为 Windows 操作系统设计的开源防火墙工具&#xff0c;旨在为用户提供全面的网络安全保护。它基于 Windows 过滤平台&#xff08;WFP&#xff09;&#xff0c;能够与系统无缝集成&#xff0c;确保高效的网络流量管理和安全防护。该软件支持实时监控网络流…...

Nginx实战技巧(Practical Tips for nginx)

引言 简介 ‌Nginx&#xff08;发音为 "engine-x"&#xff09;是一个高性能的HTTP和反向代理服务器.‌ Nginx以其高并发处理能力、低资源消耗和灵活的配置而闻名&#xff0c;适用于高流量的Web服务器和应用程序。‌ Nginx的主要功能包括&#xff1a; ‌HTTP服务器…...

YOLOv8:目标检测与实时应用的前沿探索

随着深度学习和计算机视觉技术的迅速发展&#xff0c;目标检测&#xff08;Object Detection&#xff09;一直是研究热点。YOLO&#xff08;You Only Look Once&#xff09;系列模型作为业界广受关注的目标检测框架&#xff0c;凭借其高效、实时的特点&#xff0c;一直迭代更新…...

解锁数字经济新动能:探寻 Web3 核心价值

随着科技的快速发展&#xff0c;我们正迈入一个全新的数字时代&#xff0c;Web3作为这一时代的核心构成之一&#xff0c;正在为全球数字经济带来革命性的变革。本文将探讨Web3的核心价值&#xff0c;并如何推动数字经济的新动能。 Web3是什么&#xff1f; Web3&#xff0c;通常…...

Lua 环境的安装

1.安装Lua运行环境 本人采用的是在windows系统中使用cmd指令方式进行安装&#xff0c;安装指令如下&#xff1a; winget install "lua for windows" 也曾使用可执行程序安装过&#xff0c;但由于电脑是加密电脑&#xff0c;最后都已失败告终。使用此方式安装可以安…...

Object类(2)

大家好&#xff0c;今天我们继续来看看Object类中一些成员方法&#xff0c;这些方法在实际中有很大的用处&#xff0c;话不多说&#xff0c;来看。 注&#xff1a;所有类都默认继承Object类的&#xff0c;所以可调用Object类中的方法&#xff0c;如equals&#xff0c;也可以发生…...

汽车网络信息安全-ISO/SAE 21434解析(中)

目录 第七章-分布式网络安全活动 1. 供应商能力评估 2. 报价 3. 网络安全职责界定 第八章-持续的网络安全活动 1. 网路安全监控 2. 网络安全事件评估 3. 漏洞分析 4. 漏洞管理 第九章-概念阶段 1. 对象定义 2. 网路安全目标 3. 网络安全概念 第十章 - 产品开发 第十…...

fatal error C1083: ޷[特殊字符]ļ: openssl/opensslv.h: No such file or directory

一、环境 1. Visual Studio 2017 2. edk2&#xff1a;202305 3. Python&#xff1a;3.11.4 二、 fatal error C1083: ޷&#xbfab0;ļ: openssl/opensslv.h: No such file or directory 上图出现这个警告&#xff0c;不用管。 出现Done&#xff0c;说明编译成功。 执行上…...

C#System.Threading.Timer定时器意外回收注意事项

System.Threading.Timer定时器使用时会出现意外回收的情况。具体解释如下: 只要在使用 Timer,就必须保留对它的引用。对于任何托管对象,如果没有对 Timer 的引用,计时器会被垃圾回收。即使 Timer 仍处在活动状态,也会被回收。 实例对比测试 实例 定义两个类,其中一个…...

20.Word:小谢-病毒知识的科普文章❗【38】

目录 题目​ NO1.2.3文档格式 NO4.5 NO6.7目录/图表目录/书目 NO8.9.10 NO11索引 NO12.13.14 每一步操作完&#xff0c;确定之后记得保存最后所有操作完记得再次删除空行 题目 NO1.2.3文档格式 样式的应用 选中应用段落段落→开始→选择→→检查→应用一个一个应用ctr…...

vue3底层原理和性能优化

Vue 3 在底层原理和性能优化方面做了许多改进&#xff0c;以下是一些主要的优化点和原理&#xff1a; 1. 虚拟 DOM 的改进 静态树提升&#xff1a;Vue 3 能够检测到静态组件&#xff08;即不依赖响应式数据的组件&#xff09;并将其提升到渲染函数之外&#xff0c;从而减少不…...

Ubuntu介绍、与centos的区别、基于VMware安装Ubuntu Server 22.04、配置远程连接、安装jdk+Tomcat

目录 ?编辑 一、Ubuntu22.04介绍 二、Ubuntu与Centos的区别 三、基于VMware安装Ubuntu Server 22.04 下载 VMware安装 1.创建新的虚拟机 2.选择类型配置 3.虚拟机硬件兼容性 4.安装客户机操作系统 5.选择客户机操作系统 6.命名虚拟机 7.处理器配置 8.虚拟机内存…...

金融级分布式数据库如何优化?PawSQL发布OceanBase专项调优指南

前言 OceanBase数据库作为国产自主可控的分布式数据库&#xff0c;在金融、电商、政务等领域得到广泛应用&#xff0c;优化OceanBase数据库的查询性能变得愈发重要。PawSQL为OceanBase数据库提供了全方位的SQL性能优化支持&#xff0c;助力用户充分发挥OceanBase数据库的性能潜…...

springboot 动态线程池

在Spring Boot中&#xff0c;可以使用ThreadPoolTaskExecutor类来创建动态线程池。以下是一个示例&#xff1a; 首先&#xff0c;需要在配置文件中配置线程池的属性&#xff0c;例如最小线程数、最大线程数、线程存活时间等。可以在application.properties或application.yml中…...

【PySide6快速入门】qrc资源文件的使用

文章目录 PySide6快速入门&#xff1a;qrc资源文件的使用前言什么是qrc文件&#xff1f;qrc文件的作用&#xff1a; qrc文件可以干什么&#xff1f;如何创建qrc文件&#xff1f;1. 创建.qrc文件2. 使用rcc工具编译.qrc文件 如何引用qrc文件并使用资源&#xff1f;示例代码&…...

【creo】CREO配置快捷键方式和默认单位

了解CREO工作目录设置 设置快捷方式启动目录&#xff0c;就能自动加载其中的配置。 一、通过键盘快捷方式 保存配置 creo_parametric_customization.ui 文件&#xff1a; 二、通过映射键录制 通过这种方式可以监听鼠标的点击事件。使用键盘快捷方式无法找到需要的动作时候可…...

STM32使用VScode开发

文章目录 Makefile形式创建项目新建stm项目下载stm32cubemx新建项目IED makefile保存到本地arm gcc是编译的工具链G++配置编译Cmake +vscode +MSYS2方式bilibiliMSYS2 统一环境配置mingw32-make -> makewindows环境变量Cmake CmakeListnijia 编译输出elfCMAKE_GENERATOR查询…...

数据结构与算法再探(六)动态规划

目录 动态规划 (Dynamic Programming, DP) 动态规划的基本思想 动态规划的核心概念 动态规划的实现步骤 动态规划实例 1、爬楼梯 c 递归&#xff08;超时&#xff09;需要使用记忆化递归 循环 2、打家劫舍 3、最小路径和 4、完全平方数 5、最长公共子序列 6、0-1背…...

若依基本使用及改造记录

若依框架想必大家都了解得不少&#xff0c;不可否认这是一款及其简便易用的框架。 在某种情况下&#xff08;比如私活&#xff09;使用起来可谓是快得一匹。 在这里小兵结合自身实际使用情况&#xff0c;记录一下我对若依框架的使用和改造情况。 一、源码下载 前往码云进行…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...