《数据结构、算法与应用C++语言描述》-优先级队列-大根堆的C++实现

优先级队列

完整可编译运行代码见:Github::Data-Structures-Algorithms-and-Applications/_25Priority queue

定义

优先级队列(priority queue)是0个或多个元素的集合,每个元素都有一个优先权或值,对优先级队列执行的操作有1)查找一个元素;2)插入一个新元素;3)删除一个元素。与这些操作分别对应的函数是top、push和pop。在最小优先级队列(min priority queue)中,查找和删除的元素都是优先级最小的元素;在最大优先级队列(max priority queue)中,查找和删除的元素都是优先级最大的元素。优先级队列的元素可以有相同的优先级,对这样的元素,查找与删除可以按任意顺序处理。

抽象数据类型

最大优先级队列的抽象数据类型说明如ADT 12-1所示,最小优先级队列的抽象数据类型说明与之类似,只是top的pop函数不同,查找和删除的都是优先级最小的元素。

在这里插入图片描述

定义

定义 12-1 一棵大根树(小根树)是这样一棵树,其中每个节点的值都大于(小于)或等于其子节点(如果有子节点的话)的值。

定义 12-2 一个大根堆(小根堆)既是大根树(小根树)也是完全二叉树。

在大根树或小根树中,节点的子节点个数可以任意,不一定是二叉树。

必须满足是大(小)根树同时是完全二叉树才能称为大(小)根堆。

堆是完全二叉树,具有n个元素的堆的高度为 ⌈ l o g 2 ( n + 1 ) ⌉ \lceil log_2(n+1)\rceil log2n+1。因此,如果能够在 O ( h e i g h t ) O(height) O(height)时间内完成插入和删除操作,那么这些操作的复杂性为 O ( l o g n ) O(logn) O(logn)

大(小)根堆使用数组存储。以层序遍历的顺序存储元素。

大根堆的插入

由于大根堆是完全二叉树,所以在插入元素时,一定会在完全二叉树的最后一层的最后一个元素后添加一个节点。插入元素的步骤是新元素插入新节点,然后沿着从新节点到根节点的路径,执行一趟起泡操作,将新元素与其父节点的元素比较交换,直到后者大于或等于前者为止。如下图所示,如果插入元素1,可以将其直接作为节点2的左孩子。但是如果插入元素5,就需要执行起泡操作。

在这里插入图片描述

大根堆的删除

在大根堆中删除一个元素,就是删除根节点的元素。

大根堆使用数组存储,以层序遍历的顺序存储,因此数组存储的第一个节点就是最大元素。删除操作顺序为,首先找到数组存储的最后一个元素,将该元素使用temp变量暂存起来,并删除最后一个元素。然后尝试将temp放到第一个元素,这样不满足大根堆的定义,因此把根元素的左右元素的大者移到根节点。移动后形成一个空位,尝试将temp放到该空位,如果满足该节点元素大于等于其孩子节点元素,那么放置成功,删除操作完成;否则,继续选择空位的左右孩子的大者移动到空位,以此类推,直到找到合适的位置放置temp,删除操作完成。

如图12-4删除图12-3 d)的根节点。

在这里插入图片描述

大根堆的初始化

初始时,要向堆中插入n(n>0)个元素。插入操作所需的总时间为 O ( n l o g n ) O(nlogn) O(nlogn)。也可以用不同的策略在 O ( n ) O(n) O(n)时间内完成堆的初始化。

首先是拿到一个数组,数组的元素按任意顺序。该数组可以转化为一个完全二叉树,需要做的是将完全二叉树转化为大根堆。从最后一个具有孩子的节点开始,如果以这个元素为根的子树是大根堆,则不做操作;如果以这个元素为根的子树不是大根堆,则需要将这个子树调整为大根堆。然后一次检查倒数第二个、倒数第三个子树,直到检查到第一个元素为根的树为止。

代码

template<class T>
void maxHeap<T>::initialize(T *theHeap, int theSize)
{delete [] heap;heap = theHeap;// 数组已经指定了heapSize = theSize;// 从最后一个有孩子节点的节点开始for (int root = heapSize / 2; root >= 1; root--){T rootElement = heap[root];int child = 2 * root; // 当前节点的左孩子节点while (child <= heapSize){// 找到孩子节点中的较大者if (child < heapSize && heap[child] < heap[child + 1])child++;// 如果rootElement大于等于孩子节点的较大者,那么就终止循环if (rootElement >= heap[child])break;// 如果rootElement小于孩子节点的较大者,就在父亲节点放置孩子节点heap[child / 2] = heap[child];child *= 2;// 找到较大孩子节点的孩子节点}// 如果孩子节点的较大者小于rootElement,就将rootElement作为孩子节点的父亲heap[child / 2] = rootElement;}
}

复杂性

在大根堆的初始化程序 initialize函数中,如果元素个数为 n(即theSize=n),那么for 循环的每次迭代所需时间为 O ( l o g n ) O(logn) O(logn),迭代次数为 n / 2 n/2 n/2,因此initialize函数的复杂性为 O ( n l o g n ) O(nlogn) O(nlogn)。注意,O表示法提供算法复杂性的上限。实际应用中,initialize的复杂性要比上限 O ( n l o g n ) O(nlogn) O(nlogn)好一些。经过更仔细的分析,我们得出真正的复杂性为 Θ ( n ) Θ(n) Θ(n)

在 initialize 函数中,while 循环的每一次迭代所需时间为 O ( h i ) O(h_i) O(hi),其中 h i h_i hi是以位置i 为根节点的子树的高度。完全二叉树heap[1:n]的高度为 h = ⌈ l o g 2 ( n + 1 ) ⌉ h=\lceil log_2(n+1)\rceil h=log2(n+1)⌉。在树的第j层,最多有 2 j − 1 2^{j-1} 2j1个节点。因此最多有 2 j − 1 2^{j-1} 2j1个节点具有相同的高度 h i = h − j + 1 h_i=h-j+1 hi=hj+1。于是大根堆的初始化时间为:

在这里插入图片描述

因为for循环执行n/2次迭代,所以复杂性为2(n)。将两者综合考虑,得到initialize的复杂性为 Θ ( n ) Θ(n) Θ(n)

堆与STL

STL的类 priority_queue利用了基于向量的堆来实现大根堆,它允许用户自己制定优先级的比较函数,因此,这个类也可以用于实现小根堆。

代码

main.cpp

/*
Project name :			_25Priority_queue
Last modified Date:		2023年11月29日21点08分
Last Version:			V1.0
Descriptions:			优先级队列——大根堆main函数
*/
#include "maxHeap.h"
int main() {maxHeapTest();return 0;
}

maxHeap.h

/*
Project name :			_25Priority_queue
Last modified Date:		2023年11月29日21点08分
Last Version:			V1.0
Descriptions:			优先级队列——大根堆模板头文件
*/
/*[[nodiscard]]标记符可以用于提示程序员在调用有返回值的函数时不要忘记接收改函数的返回值*/#ifndef _25PRIORITY_QUEUE_MAXHEAP_H
#define _25PRIORITY_QUEUE_MAXHEAP_H
#include "maxPriorityQueue.h"
#include "_1myExceptions.h"
#include "_2myFunctions.h"
#include <iostream>
#include <sstream>
#include <algorithm>
#include <memory>using namespace std;
int maxHeapTest();
template<class T>
class maxHeap : public maxPriorityQueue<T>
{
public:explicit maxHeap(int initialCapacity = 10);~maxHeap() {heap = nullptr;}[[nodiscard]] bool empty() const {return heapSize == 0;}[[nodiscard]] int size() const {return heapSize;}const T& top(){// 返回最大元素,也就是堆顶的值if (heapSize == 0)throw queueEmpty();return heap[1];}void pop();// 向堆中弹出元素void push(const T&);// 向堆中插入元素void initialize(T *, int);// 初始化堆void deactivateArray()// 禁用数组,这个还没搞清楚怎么用{heap = nullptr; arrayLength = heapSize = 0;}void output(ostream& out) const;// 输出大根堆的所有元素
private:int heapSize;       // 存储大根堆中有多少元素int arrayLength;    // 存储大根堆的容量大小T* heap;            // 存储大根堆元素的数组
};template<class T>
maxHeap<T>::maxHeap(int initialCapacity)
{// 构造函数,容量必须>=1if (initialCapacity < 1){ostringstream s;s << "Initial capacity = " << initialCapacity << " Must be > 0";throw illegalParameterValue(s.str());}arrayLength = initialCapacity + 1;heap = new T(arrayLength);heapSize = 0;
}// 向大顶堆中插入元素
template<class T>
void maxHeap<T>::push(const T& theElement)
{// 如果容量不够的话需要增加容量if (heapSize == arrayLength - 1){changeLength1D(heap, arrayLength, 2 * arrayLength);arrayLength *= 2;}// 从叶子节点开始起泡,将元素插入int currentNode = ++heapSize;// 如果编号i不是根节点,则其父节点的编号为[i/2](向下取整)while (currentNode != 1 && heap[currentNode / 2] < theElement){// 父节点小于子节点,不能将元素放到此处heap[currentNode] = heap[currentNode / 2]; // 将父节点放到currentNode出currentNode /= 2;                          // 当前节点的index转移到父节点}// 直到父节点大于等于theElement,将theElement放到当前位置heap[currentNode] = theElement;
}// 删除大顶堆的最大元素
// 在大根堆是二叉树时可以这样弄
template<class T>
void maxHeap<T>::pop()
{// 如果大顶堆元素个数为0,那么抛出queueEmpty异常if (heapSize == 0)throw queueEmpty();// 删除数组中第一个元素,也就是根节点的元素heap[1].~T();// 找到大顶堆的最后一排的最后一个元素T lastElement = heap[heapSize--];// 当前节点与其孩子节点的indexint currentNode = 1,child = 2;while (child <= heapSize){// 找到孩子节点中的较大者if (child < heapSize && heap[child] < heap[child + 1]) // 这里只考虑了两个孩子,因此大根堆是二叉树child++;// 如果lastElement大于等于孩子节点的较大者,就终止循环,说明找到了lastElement可以放置的位置if (lastElement >= heap[child])break;// 如果没找到放置lastElement的位置,就在currentNode放置孩子节点中的较大者heap[currentNode] = heap[child];currentNode = child;// 现在空位就变成了刚刚移动的孩子节点child *= 2;// 其孩子的index就是2倍的child}heap[currentNode] = lastElement;// 如果找到位置了就直接将最后一个元素放置到找到的位置上
}template<class T>
void maxHeap<T>::initialize(T *theHeap, int theSize)
{delete [] heap;// 数组已经指定了heap = theHeap;heapSize = theSize;// 从最后一个有孩子节点的节点开始for (int root = heapSize / 2; root >= 1; root--){T rootElement = heap[root];int child = 2 * root; // 当前节点的左孩子节点while (child <= heapSize){// 找到孩子节点中的较大者if (child < heapSize && heap[child] < heap[child + 1])child++;// 如果rootElement大于等于孩子节点的较大者,那么就终止循环if (rootElement >= heap[child])break;// 如果rootElement小于孩子节点的较大者,就在父亲节点放置孩子节点heap[child / 2] = heap[child];child *= 2;// 找到较大孩子节点的孩子节点}// 如果孩子节点的较大者小于rootElement,就将rootElement作为孩子节点的父亲heap[child / 2] = rootElement;}
}template<class T>
void maxHeap<T>::output(ostream& out) const
{// 输出大顶堆中的所有元素for(T* i = heap + 1; i < heap + heapSize + 1; i++)cout << *i << " ";cout << endl;
}// 重载输出操作符 <<
template <class T>
ostream& operator<<(ostream& out, const maxHeap<T>& x)
{x.output(out); return out;}#endif //_25PRIORITY_QUEUE_MAXHEAP_H

maxHeap.cpp

/*
Project name :			_25Priority_queue
Last modified Date:		2023年11月29日21点08分
Last Version:			V1.0
Descriptions:			优先级队列——大根堆模板源文件
*/
#include "maxHeap.h"using namespace std;int maxHeapTest()
{// test constructor and pushmaxHeap<int> h(3);h.push(10);h.push(20);h.push(5);cout << "Heap size is " << h.size() << endl;cout << "Elements in array order are" << endl;cout << h << endl;h.push(15);h.push(30);cout << "Heap size is " << h.size() << endl;cout << "Elements in array order are" << endl;cout << h << endl;// test top and popcout << "The max element is " << h.top() << endl;h.pop();cout << "The max element is " << h.top() << endl;h.pop();cout << "The max element is " << h.top() << endl;h.pop();cout << "Heap size is " << h.size() << endl;cout << "Elements in array order are" << endl;cout << h << endl;// test initializeint z[10];for (int i = 1; i < 10; i++)z[i] = i;h.initialize(z, 9);cout << "Elements in array order are" << endl;cout << h << endl;return 0;
}

maxPriorityQueue.h

/*
Project name :			_25Priority_queue
Last modified Date:		2023年11月29日21点08分
Last Version:			V1.0
Descriptions:			优先级队列——大根堆抽象数据类型
*/#ifndef _25PRIORITY_QUEUE_MAXPRIORITYQUEUE_H
#define _25PRIORITY_QUEUE_MAXPRIORITYQUEUE_Htemplate<class T>
class maxPriorityQueue
{
public:virtual ~maxPriorityQueue() = default;[[nodiscard]] virtual bool empty() const = 0;// return true iff queue is empty[[nodiscard]] virtual int size() const = 0;// return number of elements in queuevirtual const T& top() = 0;// return reference to the max elementvirtual void pop() = 0;// remove the top elementvirtual void push(const T& theElement) = 0;// add theElement to the queue
};
#endif //_25PRIORITY_QUEUE_MAXPRIORITYQUEUE_H

_1myExceptions.h

/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月13日17点38分
Last Version:			V1.0
Descriptions:			综合各种异常
*/
#pragma once
#ifndef _MYEXCEPTIONS_H_
#define _MYEXCEPTIONS_H_
#include <string>
#include<iostream>
#include <utility>using namespace std;// illegal parameter value
class illegalParameterValue : public std::exception
{
public:explicit illegalParameterValue(string theMessage = "Illegal parameter value"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};// illegal input data
class illegalInputData : public std::exception
{
public:explicit illegalInputData(string theMessage = "Illegal data input"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};// illegal index
class illegalIndex : public std::exception
{
public:explicit illegalIndex(string theMessage = "Illegal index"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};// matrix index out of bounds
class matrixIndexOutOfBounds : public std::exception
{
public:explicit matrixIndexOutOfBounds(string theMessage = "Matrix index out of bounds"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};// matrix size mismatch
class matrixSizeMismatch : public std::exception
{
public:explicit matrixSizeMismatch(string theMessage ="The size of the two matrics doesn't match"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};// stack is empty
class stackEmpty : public std::exception
{
public:explicit stackEmpty(string theMessage ="Invalid operation on empty stack"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};// queue is empty
class queueEmpty : public std::exception
{
public:explicit queueEmpty(string theMessage ="Invalid operation on empty queue"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};// hash table is full
class hashTableFull : public std::exception
{
public:explicit hashTableFull(string theMessage ="The hash table is full"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};// edge weight undefined
class undefinedEdgeWeight : public std::exception
{
public:explicit undefinedEdgeWeight(string theMessage ="No edge weights defined"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};// method undefined
class undefinedMethod : public std::exception
{
public:explicit undefinedMethod(string theMessage ="This method is undefined"){message = std::move(theMessage);}void outputMessage() {cout << message << endl;}
private:string message;
};
#endif

_2myFunctions.h

/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月13日17点38分
Last Version:			V1.0
Descriptions:			综合各种非成员函数
*/
#pragma once
#ifndef _MYFUNCTIONS_H_
#define _MYFUNCTIONS_H_
#include<iostream>
#include "_1myExceptions.h"
#include<cmath>
#include <exception>
#include <memory>using std::min;
using std::endl;
using std::cout;
using std::bad_alloc;
/*交换两数据*/
template<class V>
void Swap(V& a, V& b)
{V temp = a;a = b;b = temp;
}
/*
作用:将数组的长度加倍
输入:指针a指向需要改变长度的数组,oldLength表示数组原来的长度,newLength表示需要改变的新长度
结果:将数组扩容/缩容 为newLength
*/
template<class T>
void changeLength(T*& a, int oldLength, int newLength)
{if (newLength < 0)throw illegalParameterValue("new length must be >= 0");T* temp = new T[newLength];int number = min(oldLength, newLength);copy(a, a + number, temp);delete[] a;a = temp;
}
/*遍历一维数组*/
template<class T>
void traverse1dArray(T* x, int length)
{for (int i = 0; i < length; i++)cout << x[i] << " ";cout << endl;
}
/*创建二维数组*/
template <class T>
bool make2dArray(T**& x, int numberOfRows, int numberOfColumns)
{try {//行指针x = new T * [numberOfRows];//为每一行分配内存for (int i = 0; i < numberOfRows; i++)x[i] = new int[numberOfColumns];return true;}catch (bad_alloc) { return false; }
}/*遍历二维数组*/
template<class T>
void traverse2dArray(T**& x, int numberOfRows, int numberOfColumns)
{for (int i = 0; i < numberOfRows; i++){for (int j = 0; j < numberOfColumns; j++){cout.width(4);cout << x[i][j] << "  ";}cout << endl;}
}
template<class T>
void changeLength1D(T*& a, int oldLength, int newLength)
{if (newLength < 0)throw illegalParameterValue("new length must be >= 0");T* temp = new T[newLength];              // new arrayint number = min(oldLength, newLength);  // number to copycopy(a, a + number, temp);a = temp;
}
#endif

运行结果

"C:\Users\15495\Documents\Jasmine\prj\_Algorithm\Data Structures, Algorithms and Applications in C++\_25Priority queue\cmake-build-debug\_25Priority_queue.exe"
Heap size is 3
Elements in array order are
20 10 5Heap size is 5
Elements in array order are
30 20 5 10 15The max element is 30
The max element is 20
The max element is 15
Heap size is 2
Elements in array order are
10 5Elements in array order are
9 8 7 4 5 6 3 2 1Process finished with exit code 0

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

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

相关文章

Sitecore “Insert Link“ 时,默认 Ttarget 设置

一、简介 在我们使用 Sitecore “Insert Link“ 通常会插入站内的链接&#xff0c;通常情况下 Sitecore 默认的 Target 时 Custom&#xff0c;如果不想跳新的浏览器 Tab &#xff0c;就需要手动修改为 Active Browser。如何默认就是 Active Browser 呢&#xff0c;这就是我们今…

[问题解决] no CUDA-capable device is detected

先说环境&#xff0c;在docker下的gpu环境ffmpeg&#xff0c;然后今天突然无法使用&#xff0c;使用时出现如下图所示&#xff1a; 看着报错大致内容是找不到设备&#xff0c;网上寻找一番没有有用的东西&#xff0c;于是决定自己解决&#xff0c;仔细察看一番后&#xff0c;猜…

MQTT发布_订阅架构(Pub_Sub)

MQTT发布/订阅架构&#xff08;Pub/Sub&#xff09; 本文中&#xff0c;将深入研究Pub/Sub架构&#xff0c;在软件架构中一个消息模式&#xff0c;它支持不同组件或系统之间以解耦的方式进行通信。 在前一片文章[MQTT简介]http://t.csdnimg.cn/6lNeZ中&#xff0c;对MQTT有一个…

注解Annotation - Java

注解Annotation 一、介绍二、使用三、三个基本的Annotation四、JDK内置的基本注解类型1、Override2、Deprecated3、SuppressWarnings 五、JDK的元注解1、Retention2、Target3、Documented4、Inherited 一、介绍 注解&#xff08;Annotation&#xff09;也被称为元数据&#xf…

算法通关村第一关—青铜挑战—用Java基本实现各种链表操作

文章目录 第一关—链表【青铜挑战】1.1 单链表的概念1.2 链表的相关概念1.3 创建链表 - Java实现1.4 链表的增删改查1.4.1 遍历单链表 - 求单链表长度1.4.2 链表插入 - 三种位置插入&#xff08;1&#xff09;在链表的表头插入&#xff08;2&#xff09;在链表的中间插入&#…

Docker安装Elasticsearch以及ik分词器

Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎&#xff0c;能够解决不断涌现出的各种用例。作为 Elastic Stack 的核心&#xff0c;Elasticsearch 会集中存储您的数据&#xff0c;让您飞快完成搜索&#xff0c;微调相关性&#xff0c;进行强大的分析&#xff…

量子芯片:引领计算技术的新篇章

量子芯片:引领计算技术的新篇章 引言 随着量子计算的飞速发展,量子芯片作为量子计算机的核心组件,日益受到人们的关注。量子芯片的出现,不仅有望推动计算技术的革新,更将在信息安全、药物研发、金融投资等领域掀起巨大的变革。在本篇博客中,我们将深入探讨量子芯片的原理…

使用STM32微控制器实现烟雾传感器的接口和数据处理

烟雾传感器是常见的安全检测装置&#xff0c;通过检测空气中的烟雾浓度来提醒用户有潜在的火灾风险。本文将介绍如何使用STM32微控制器来实现烟雾传感器的接口和数据处理。包括硬件连接、采集模拟信号、数字信号处理和报警策略等方面。同时&#xff0c;给出相应的代码示例。 一…

mac 聚焦搜索不显示

我是连搜索框都不显示&#xff0c;不是搜索结果显示异常 点右上角的搜索按钮都毫无反应 我检查过快捷键之类的设置&#xff0c;都正常&#xff0c;最后是通过删除文件解决的 cd ~/Library/Preferences/ rm com.apple.Spotlight.plist 重启 mac 参考 Spotlight Search Not W…

Unity引擎:创造无限可能的游戏开发平台

Unity引擎&#xff1a;创造无限可能的游戏开发平台 一、Unity引擎概述1.1 什么是Unity引擎&#xff1f;1.2 Unity引擎的特点和优势 二、Unity开发环境和工具2.1 Unity编辑器2.2 支持的平台2.3 脚本语言2.4 图形和音频工具 三、Unity游戏开发流程四、示例应用场景五、结论&#…

MySQL-函数

一、统计函数 CREATE TABLE student (id INT NOT NULL DEFAULT 1,name varchar(20) not null default ,chinese float not null default 0.0,english float not null default 0.0,math float not null default 0.0 );insert into student values (1,曹操,77,89,85);insert int…

postgres在docker中使用

记录个人开发过程中postgres在docker中的使用&#xff0c;以便后续查看。 Dockerfile 个人是在M1电脑上开发&#xff0c;所以platform使用linux/amd64来兼容amd芯片。 FROM --platformlinux/amd64 postgres:16.1-alpine COPY ./poetrydb.sql /docker-entrypoint-initdb.d/po…

Jenkins 如何查看已经记录登录服务器的凭证密码

文章目录 一、背景描述二、解决方案一&#xff08;查看所有账号密码&#xff09;三、解决方案二&#xff08;查询指定账号密码&#xff09; 一、背景描述 在日常的开发过程中&#xff0c;有时候会出现忘记开发、测试服务器的登录密码的情况。此时恰巧 Jenkins 上记录了登录该主…

【笔记】windows+pytorch:部署一下stable diffusion和NeRF

之前都是 *nix 环境使用 pytorch&#xff0c;这次尝试了一下windows。 我们来部署下流行性高的stable diffusion和我觉得实用性比stable diffusion高多了的NeRF Stable Diffusion 其实&#xff0c;我也不知道要写啥&#xff0c;都是按照步骤做就好了&#xff0c;后面等有时间…

如何快速生成项目目录结构树?

经常在网上看到下面这种由一个项目&#xff0c;生成一个结构树&#xff0c;你知道它是怎么生成的吗&#xff1f; 这就是利用本文要介绍的一个工具——Treer&#xff0c;treer就是一款专门用来快速生成目录结构树的命令行工具。 第一步&#xff1a;安装treer 在终端执行全局…

蓝桥杯第199题 扫地机器人 暴力优化 二分法 简单题 C++

题目 扫地机器人 - 蓝桥云课 (lanqiao.cn)https://www.lanqiao.cn/problems/199/learning/?page1&first_category_id1&name%E6%89%AB%E5%9C%B0%E6%9C%BA%E5%99%A8%E4%BA%BA 思路和解题方法 首先&#xff0c;通过cin语句输入了终点位置n和障碍物数量k。使用一个数组a来…

微服务学习|初识elasticsearch、操作索引库、文档操作、RestClient操作索引库、RestClient操作文档

初识elasticsearch 什么是elasticsearch&#xff1f; elasticsearch是一款非常强大的开源搜索引擎&#xff0c;可以帮助我们从海量数据中快速找到需要的内容。 elasticsearch结合kibana、Logstash、Beats&#xff0c;也就是elastic stack (ELK)。被广泛应用在日志数据分析、实…

python+pytest接口自动化(4)-requests发送get请求

python中用于请求http接口的有自带的urllib和第三方库requests&#xff0c;但 urllib 写法稍微有点繁琐&#xff0c;所以在进行接口自动化测试过程中&#xff0c;一般使用更为简洁且功能强大的 requests 库。下面我们使用 requests 库发送get请求。 requests库 简介 request…

C# WPF上位机开发(倒计时软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 生活当中&#xff0c;我们经常会遇到倒计时的场景&#xff0c;比如体育运动的时候、考试的时候等等。正好最近我们学习了c# wpf开发&#xff0c;完…

记录一次现网问题排查(分享查域名是否封禁小程序)

背景&#xff1a; 收到工单反馈说现网业务一个功能有异常&#xff0c;具体现象是tc.hb.cn域名无法访问&#xff0c;客户地区是河南省&#xff0c;这里记录下排查过程和思路。 首先梳理链路 客户端域名 tc.hb.cn cname—> domainparking-dnspod.cn(新加坡clb)—> snat—&…