【树与二叉树】二叉树顺序结构实现以及堆的概念及结构--详解介绍

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:数据结构
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • 1. 二叉树顺序结构
  • 2.堆
    • 2.1 堆的概念及结构
    • 2.1.1 概念
    • 2.1.2 堆的性质
    • 2.2 堆的概念选择题
    • 2.3 堆的实现
      • ①.堆的初始化:
      • ②.堆的插入(向上调整算法):
      • ③.堆的删除(向下调整算法):
      • ④.取堆顶数据:
      • ⑤.堆中数据个数:
      • ⑥.堆的判空:
      • ⑦.堆的销毁:
      • ⑦.堆的打印:
    • 2.4 堆的代码实现
      • Heap.h 用于函数的声明
      • Heap.c 用于函数的定义
      • Test.c 用于测试函数
  • 3.总结:

1. 二叉树顺序结构

普通二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储。

注意 操作系统数据结构中都有栈和堆的概念,这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。
在这里插入图片描述

2.堆

2.1 堆的概念及结构

2.1.1 概念

堆分为小根堆大根堆,根节点始终小于子节点称为小根堆,相反根节点始终大于子节点则称为大根堆。换句话说,将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

▶ 大(根)堆,树中所有父亲都大于或者等于孩子,且大堆的根是最大值;
在这里插入图片描述

▶ 小(根)堆,树中所有父亲都小于或者等于孩子,且小堆的根是最小值;
在这里插入图片描述

2.1.2 堆的性质

▶ 堆中某个节点的值总是不大于或不小于其父节点的值
▶ 堆总是一棵完全二叉树

2.2 堆的概念选择题

1、下列关键字序列为堆的是( )
A. 100, 60, 70, 50, 32, 65
B. 60, 70, 65, 50, 32, 100
C. 65, 100, 70, 32, 50, 60
D. 70, 65, 100, 32, 50, 60
E. 32, 50, 100, 70, 65, 60
F. 50, 100, 70, 65, 60, 32

  • 分析:根据堆的概念分析,A 选项为大根堆;
    在这里插入图片描述

2、已知小根堆为 8, 15, 10, 21, 34, 16, 12,删除关键字 8 之后需重建堆,在此过程中,关键字之间的比较次数是( )
A. 1
B. 2
C. 3
D. 4

  • 分析:此题考查的是建堆的过程,所以选择 C 选项
    在这里插入图片描述

3、一组记录排序码为 (5 11 7 2 3 17),则利用堆排序方法建立的初始堆为( )
A. (11 5 7 2 3 17)
B. (11 5 7 2 17 3)
C. (17 11 7 2 3 5)
D. (17 11 7 5 3 2)
E. (17 7 11 3 5 2)
F. (17 7 11 3 2 5)

  • 分析:此题考查的是堆排序建堆的过程,根据下面堆排序的过程分析,选择 C 选项
    在这里插入图片描述

4、、注,请理解下面堆应用的知识再做。最小堆 [0, 3, 2, 5, 7, 4, 6, 8],在删除堆顶元素0之后,其结果是( )
A. [3,2,5,7,4,6,8]
B. [2,3,5,7,4,6,8]
C. [2,3,4,5,7,8,6]
D. [2,3,4,5,6,7,8]

  • 分析:此题考查的是 Pop 堆顶后,重新建堆的变化,所以选择 C 选项
    在这里插入图片描述

2.3 堆的实现

1、堆向下调整算法
向下调整算法有一个前提:左右子树必须是一个堆 (包括大堆和小堆),才能调整。

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个小堆。

1.1 建堆
有一个随机值的数组,把它理解成完全二叉树,并模拟成堆 (大堆/小堆)

int array[] = {27, 15, 19, 18, 28, 34, 65, 49, 25, 37}

观察这组数据
根下面的左右子树都是小根堆,其实堆向下调整算法就是针对这种特殊数据结构

1.1.1针对于这种类型的数据应该怎么调堆
思路:从根开始与左右孩子比较,如果孩子比父亲小,则两两交换位置,再继续往下调,直到左右孩子都比父亲大或者调到叶子
在这里插入图片描述

1.1.2 如果不满足左右子树是堆,怎么调整?

int array[] = {27, 37, 28, 18, 19, 34, 65, 25, 49, 15}
根的左右子树 37、28 都不满足:这里的想法就是先让左右子树先满足;而对于左右子树 37、28 来说又需要让 37 先满足;这样依此类推直至满足堆的条件。那干脆就从倒数的第一棵树,也就是倒数的第一个非叶子节点开始调整
在这里插入图片描述

关于堆的实现我们使用标准模块化开发格式进行研究:

Heap.h:存放函数声明、包含其他头文件、定义宏。
Heap.c:书写函数定义,书写函数实现。
test.c:书写程序整体执行逻辑。

①.堆的初始化:

堆的初始化与队列相同,首先判断传入指针非空后,将其置空,并将数据置零即可。

//1、对于HeapCreate函数,结构体不是外面传进来的,而是在函数内部自己malloc空间,再创建的
/* 
HP* HeapCreate(HPDataType* a, int n)
{}
*/
//2、对于HeapInit函数,在外面定义一个结构体,把结构体的地址传进来
void HeapInit(HP* php, HPDataType* a, int n)
{
	assert(php); 
	//malloc空间(当前数组大小一样的空间)
	php->a = (HPDataType*)malloc(sizeof(HPDataType) * n);
	if (php->a == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	//使用数组初始化
	memcpy(php->a, a, sizeof(HPDataType) * n);
	php->size = n;
	php->capacity = n;
	//建堆 
	int i = 0;
	for (i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(php->a, n, i);
	}
}

②.堆的插入(向上调整算法):

因为堆的存储在物理层面上数组,但是在逻辑层面上二叉树。并且由于只有小根堆和大根堆,所以在插入数据之后要想保证其仍然是堆,就需要进行适当的调整。

插入时从尾部插入,而是否为堆取决于子节点和父节点的关系,若为小根堆则子节点要比父节点要大否则就需要交换子节点和父节点,大根堆则相反。而这种调整方式就叫做向上调整算法。

执行操作前需进行非空判断,防止堆空指针进行操作。
插入前判断空间是否足以用于此次扩容,若不足则进行扩容,直至满足插入条件后堪称插入操作,这个接口的功能实现也与队列的处理方式基本相同。
与队列的不同点在于,为了保证插入后仍然是堆,需要在插入后使用向上调整算法进行适当的调整

//向上调整算法:
//除了child的数据,前面的数构成堆
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	//parent>=0  感觉有问题 但可以使用
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
 
//堆插入:
void HeapPush(HP* php, HPDataType x)
{
	assert(php);

	//空间不够,增容
	if (php->size == php->capacity)
	{
		HPDataType* temp = (HPDataType*)realloc(php->a, php->capacity * 2 * sizeof(HPDataType));
		if (temp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		else
		{
			php->a = temp;	
		}
		php->capacity *= 2;
	}
	//将x放在最后
	php->a[php->size] = x;
	php->size++;
	//向上调整
	AdjustUp(php->a, php->size - 1);
}

③.堆的删除(向下调整算法):

堆删除的实质是删除堆顶元素,如果我们直接删除堆顶的元素,再将数据挪动,就会破坏堆的结构,所以这种方法并不可取;于是我们这里采用将堆顶的数据与最后一个数据交换,再删除最后一个数据的方法,这样就实现了堆顶数据的删除。接着我们再调整一下堆顶数据的位置即可。

在这里选择的调整方法是:将根节点与它的孩子中的较小值交换,然后再将交换后的节点作为父节点继续与它的子节点交换,直到该节点小于它的子节点,或者成为叶节点。

注意 使用这个方法有一个前提:根节点的两个子树也得是堆才行。而这种方法就叫做向下调整算法。

执行操作前需进行非空判断,防止对空指针进行操作。
删除过程同样与队列近乎一致,不同点是在删除过后为了保证删除堆顶数据后仍为堆,于是需要使用向下调整算法对删除后的结果进行适当的处理。

//向下调整算法:
//左右子树都是大堆或小堆
void AdjustDown(HPDataType* arr, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		//选出左右孩子中大的那一个
		if (child + 1 < n && arr[child] < arr[child + 1])//防止越界 右孩子存在
		//child + 1 < n 放左边 先检查
		{
			child++;//右孩子>左孩子 ++
		}
		if (arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else//父亲大于孩子 不用交换了
		{
			break;
		}
	}
}
 
//堆顶数据删除:
void HeapPop(HP* php)
{
	assert(php);
	//没有数据删除就报错
	assert(!HeapEmpty(php));
	//交换首尾
	Swap(&php->a[0], &php->a[php->size-1]);
	php->size--;
	//向下调整
	AdjustDown(php->a, php->size, 0);
}
HPDataType HeapTop(HP* php)
{
	assert(php);
	//没有数据获取就报错
	assert(!HeapEmpty(php));
	return php->a[0];
}
int HeapSize(HP* php)
{
	assert(php);
	return php->size;
}

测试删除接口功能实现:

④.取堆顶数据:

取堆顶数据操作与队列完全相同

HPDataType HeapTop(HP* php)
{
	assert(php);
	//没有数据获取就报错
	assert(!HeapEmpty(php));
	
	return php->a[0];
}

⑤.堆中数据个数:

查看堆中的数据个数操作很简单,在判断传入指针非空后,直接返回 p->size 的值,即堆中保存的数据数量即可。

int HeapSize(HP* php)
{
	assert(php);
	
	return php->size;
}

⑥.堆的判空:

堆的判空操作与队列完全相同

//堆数据判空:
bool HeapEmpty(HP* php)
{
	assert(php);
	
	return php->size == 0;
}

⑦.堆的销毁:

堆的销毁与队列相同

void HeapDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	
	php->size = php->capacity = 0;
}

⑦.堆的打印:

void HeapPrint(HP* php)
{
	assert(php);

	int i = 0;
	for (i = 0; i < php->size; i++)
	{
		printf("%d ", php->a[i]);
	}
	printf("\n");
}

2.4 堆的代码实现

注意

▶ 堆的初始化一般是使用数组进行初始化的

▶ 堆的插入数据不分头插、尾插,将数据插入后,原来堆的属性不变

先放在数组的最后一个位置,再向上调整

▶ 堆的删除数据删除的是堆顶的数据,将数据删除后,原来堆的属性不变

为了效率,将第一个和最后一个元素交换,再减容,然后再调整

Heap.h 用于函数的声明

#pragma once

//头
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>

typedef int HPDataType;

//C++ -> priority_queue 在C++里用的是优先级队列,其底层就是一个堆
//大堆
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;
//函数的声明
//交换
void Swap(HPDataType* px, HPDataType* py);
//向下调整
void AdjustDown(HPDataType* arr, int n, int parent);
//向上调整
void AdjustUp(HPDataType* a, int child);
//使用数组进行初始化
void HeapInit(HP* php, HPDataType* a, int n);
//回收空间
void HeapDestroy(HP* php);
//插入x,保持它继续是堆
void HeapPush(HP* php, HPDataType x); 
//删除堆顶的数据,保持它继续是堆
void HeapPop(HP* php);
//获取堆顶的数据,也就是最值
HPDataType HeapTop(HP* php);
//判空
bool HeapEmpty(HP* php);
//堆的数据个数
int HeapSize(HP* php);
//输出
void HeapPrint(HP* php);

Heap.c 用于函数的定义

#include"Heap.h"


void Swap(HPDataType* px, HPDataType* py)
{
	HPDataType temp = *px;
	*px = *py;
	*py = temp;
}
//左右子树都是大堆或小堆
void AdjustDown(HPDataType* arr, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		//选出左右孩子中大的那一个
		if (child + 1 < n && arr[child] < arr[child + 1])//防止越界 右孩子存在
		//child + 1 < n 放左边 先检查
		{
			child++;//右孩子>左孩子 ++
		}
		if (arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else//父亲大于孩子 不用交换了
		{
			break;
		}
	}
}
//除了child的数据,前面的数构成堆
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	//parent>=0  感觉有问题 但可以使用
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
void HeapPrint(HP* php)
{
	assert(php);

	int i = 0;
	for (i = 0; i < php->size; i++)
	{
		printf("%d ", php->a[i]);
	}
	printf("\n");
}
//1、对于HeapCreate函数,结构体不是外面传进来的,而是在函数内部自己malloc空间,再创建的
/* 
HP* HeapCreate(HPDataType* a, int n)
{}
*/
//2、对于HeapInit函数,在外面定义一个结构体,把结构体的地址传进来
void HeapInit(HP* php, HPDataType* a, int n)
{
	assert(php); 
	//malloc空间(当前数组大小一样的空间)
	php->a = (HPDataType*)malloc(sizeof(HPDataType) * n);
	if (php->a == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	//使用数组初始化
	memcpy(php->a, a, sizeof(HPDataType) * n);
	php->size = n;
	php->capacity = n;
	//建堆 
	int i = 0;
	for (i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(php->a, n, i);
	}
}
void HeapDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->size = php->capacity = 0;
}
bool HeapEmpty(HP* php)
{
	assert(php);
	return php->size == 0;
}
void HeapPush(HP* php, HPDataType x)
{
	assert(php);

	//空间不够,增容
	if (php->size == php->capacity)
	{
		HPDataType* temp = (HPDataType*)realloc(php->a, php->capacity * 2 * sizeof(HPDataType));
		if (temp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		else
		{
			php->a = temp;	
		}
		php->capacity *= 2;
	}
	//将x放在最后
	php->a[php->size] = x;
	php->size++;
	//向上调整
	AdjustUp(php->a, php->size - 1);
}
void HeapPop(HP* php)
{
	assert(php);
	//没有数据删除就报错
	assert(!HeapEmpty(php));
	//交换首尾
	Swap(&php->a[0], &php->a[php->size-1]);
	php->size--;
	//向下调整
	AdjustDown(php->a, php->size, 0);
}
HPDataType HeapTop(HP* php)
{
	assert(php);
	//没有数据获取就报错
	assert(!HeapEmpty(php));
	return php->a[0];
}
int HeapSize(HP* php)
{
	assert(php);
	return php->size;
}

Test.c 用于测试函数

#include"Heap.h"

void TestHeap()
{
	int arr[] = { 27, 37, 28, 18, 19, 34, 65, 25, 49, 15 };
	HP hp;
	HeapInit(&hp, arr, sizeof(arr)/sizeof(arr[0]));
	HeapPrint(&hp);
	HeapPush(&hp, 18);
	HeapPrint(&hp);
	HeapPush(&hp, 98);
	HeapPrint(&hp);
	printf("\n\n");
	//将堆这数据结构实现好后,我们就可以利用这些接口实现排序
	while(!HeapEmpty(&hp))
	{
		printf("%d ", HeapTop(&hp));	
		HeapPop(&hp);
	}
	printf("\n");
	
}
int main()
{
	TestHeap();
	return 0;
}

3.总结:

今天我们认识并学习了二叉树顺序结构的相关概念,并且对堆的概念及结构也有了一定的了解。还对二叉树顺序存储的实例——堆的各接口功能进行了实现。下一篇博客我们将从堆的时间复杂度详解以及堆的应用—堆排序、TOP - K问题进一步介绍堆。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch:Elasticsearch 容量规划

Elasticsearch 是一个可扩展的分布式系统&#xff0c;可为企业搜索、日志聚合、可观察性和安全性提供解决方案。 Elastic 解决方案建立在一个单一、灵活的技术堆栈之上&#xff0c;可以部署在任何地方。 要在自托管或云端运行生产环境 Elasticsearch&#xff0c;需要规划基础架…

Linux硬链接与软链接

图示区别 硬链接 具有相同inode节点号的多个文件互为硬链接文件&#xff1b;删除硬链接文件或者删除源文件任意之一&#xff0c;文件实体并未被删除&#xff1b;只有删除了源文件和所有对应的硬链接文件&#xff0c;文件实体才会被删除&#xff1b;硬链接文件是文件的另一个入…

贯穿设计模式第四话--里氏替换原则

&#x1f973;&#x1f973;&#x1f973; 茫茫人海千千万万&#xff0c;感谢这一刻你看到了我的文章&#xff0c;感谢观赏&#xff0c;大家好呀&#xff0c;我是最爱吃鱼罐头&#xff0c;大家可以叫鱼罐头呦~&#x1f973;&#x1f973;&#x1f973; 从今天开始&#xff0c;将…

关于位运算的巧妙性:小乖,你真的明白吗?

一.位运算的概念什么是位运算&#xff1f;程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。位运算就是直接操作二进制数&#xff0c;那么有哪些种类的位运算呢&#xff1f;常见的运算符有与(&)、或(|)、异或(^)、…

软硬结合板设计,过孔到软板区域的间距设计多少合适

一博高速先生成员&#xff1a;王辉东 十里樱花香无边&#xff0c; 满枝芳华尽娇艳。 春风不知少年心&#xff0c; 红粉树下看如烟。 周六的下午&#xff0c;赵理工推开窗&#xff0c;一阵香风袭来&#xff0c;空气中氤氲着樱花的气息。樱花开得浪漫&#xff0c;恰似少年的…

[致敬未来的攻城狮计划 1] 使用 “FSP Configuration”(FSP 配置)透视配置器设置运行环境

开启攻城狮的成长之旅&#xff01;这是我参与的由 CSDN博客专家 架构师李肯&#xff08;http://yyds.recan-li.cn&#xff09;和 瑞萨MCU &#xff08;瑞萨电子 (Renesas Electronics Corporation) &#xff09; 联合发起的「 致敬未来的攻城狮计划 」的第 4 天&#xff0c;点击…

动态规划-不相交的线

动态规划-不相交的线 前言 动态规划中存在一类问题&#xff0c;它涉及到两个数组或链表&#xff0c;需要求解出两个数组中的最长公共子序列&#xff0c;如果要求解两个数组的最长公共子序列。如果采取最原始的方式&#xff0c;选择对第一个数组中的元素的不同排列进行有序组合…

Excel:vlookup函数

Excel:VlookUp函数VlookUp函数VlookUp函数 首先还是先放官方文档的参考&#xff1a;VLOOKUP 函数 Vlookup函数参数&#xff1a; VLOOKUP(lookup_ value, table_ array, col index_ num, [range_ lookup]) lookup_ value&#xff1a;要查找的内容&#xff1b; table_ array&a…

CloudCompare 二次开发(6)——插件中拖拽添加Qt窗口(区域生长算法为例)

目录 一、概述二、插件制作三、Cmake编译四、插件代码五、结果展示一、概述 手动拖拽的方式搭建Qt对话框界面的制作流程,以PCL中的点云区域生长算法为例进行制作。 二、插件制作 1、将....\plugins\example路径下的ExamplePlugin复制一份并修改名字为CCPointCloudProcess。 …

大数据之Spark基础环境

文章目录前言一、Spark概述&#xff08;一&#xff09;Spark是什么&#xff08;二&#xff09;Spark的四大特点&#xff08;三&#xff09;Spark的风雨十年&#xff08;四&#xff09;Spark框架模块&#xff08;五&#xff09;Spark通信框架总结前言 #博学谷IT学习技术支持# 本…

【lwIP(第四章)】网络接口

目录一、lwIP网络接口简介二、lwIP的netif结构三、lwIP的netif相关函数1. lwIP网络接口的全局变量2. netif_add()函数3. netif_remove()函数4. netif_set_default()函数一、lwIP网络接口简介 lwIP协议栈支持多种不同的网络接口&#xff08;网卡&#xff09;&#xff0c;由于网卡…

OSPF----优化

优化主要目的---减少LSA的更新量以及数量 路由汇总&#xff08;减少骨干区域的LSA更新量&#xff09;OSPF特殊秋雨&#xff08;减少非骨干区域的LSA更新量&#xff09;OSPF路由汇总&#xff08;路由聚合&#xff09; OSPF路由汇总是由手工部署的OSPF的汇总称为---区域汇总&…

Swagger快速入门【基础总结】

Swagger 背景信息 什么是前后端分离&#xff1a; 即: Vue Springboot 开发模式 以前是后端时代(后端是主力)&#xff1a;前端只用管理静态页面&#xff1b;html—>后端。 前后端分离时代&#xff1a; 前端 &#xff1a;前端控制层、视图层【前端团队】后端&#xff1a;后…

客户端安装SSH工具Xshell图解

一、客户端安装SSH工具 windows客户端&#xff1a;安装Putty、XShell 或者 SecureCRT Linux客户端&#xff1a;yum install openssh-clients macOS客户端&#xff1a;默认已经安装了SSH客户端 我们这里安装windows客户端&#xff0c;选择XShell 工具。 Xshell5、Xftp5下载&am…

Linux系统之安装PostgreSQL数据库

Linux系统之安装PostgreSQL数据库一、PostgreSQL介绍1.PostgreSQL简介2.PostgreSQL特点二、本次实践介绍1.本次实践介绍2.实践环境介绍三、配置PostgreSQL的yum仓库源1.检查本地是否部署PostgreSQL2.配置镜像源3.检查yum仓库镜像源状态四、安装PostgreSQL1.安装PostgreSQL2.初始…

GPIO的八种模式分析

GPIO是general purpose input output,即通用输入输出端口&#xff0c;作用是负责外部器件的信息和控制外部器件工作。 GPIO有如下几个特点&#xff1a;1.不同型号的IO口数量不同&#xff1b;2&#xff0c;反转快速&#xff0c;每次翻转最快只需要两个时钟周期&#xff0c;以ST…

dubbo的SPI机制和服务暴露,引用原理

一、SPI引入&#xff1a;spi标准&#xff1a;1、需要在 classpath 下创建一个目录&#xff0c;该目录命名必须是&#xff1a;META-INF/service2、在该目录下创建一个 properties 文件&#xff0c;该文件需要满足以下几个条件 &#xff1a;2.1 文件名必须是扩展的接口的全路径名…

量子运算-比算子描述更广泛的一类刻画量子态在客观世界演化的数学工具

参考链接&#xff1a;1.1 量子运算 - 知乎 (zhihu.com)一个量子操作&#xff08;包括量子测量和量子信道&#xff09;指的是把一个密度矩阵变成另一个密度矩阵的变换&#xff0c;一般记为 背景演化算符是酉的。这里考虑考虑特殊的演化-测量。测量对应的算子是投影算子&#xff…

刘禹锡最经典诗文10首,每一首都是千古名作,读懂受益一生

他是唐代最乐观的诗人&#xff0c;是比他的好友乐天更乐天的人&#xff01;他与柳宗元并称“刘柳”&#xff0c;与韦应物、白居易合称“三杰”&#xff0c;并与白居易合称“刘白”。他是在唐代诗人中&#xff0c;出了名的豪放豁达的刘禹锡。白居易称他为“诗豪”。自“永贞革新…

Elasticsearch:理解 Master,Elections,Quorum 及 脑裂

集群中的每个节点都可以分配多个角色&#xff1a;master、data、ingest、ml&#xff08;机器学习&#xff09;等。 我们在当前讨论中感兴趣的角色之一是 master 角色。 在 Elasticsearch 的配置中&#xff0c;我们可以配置一个节点为 master 节点。master 角色的分配表明该节点…