【数据结构】二叉树的概念及堆

 前言

我们已经学过了顺序表、链表、栈和队列这些属于线性结构的数据结构,那么下面我们就要学习我们第一个非线性结构,非线性结构又有哪些值得我们使用的呢?那么接下来我们就将谈谈树的概念了。

1.树的概念与结构

1.1树的概念

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

  •  有一个特殊的结点,称为根结点,根节点没有前驱结点。
  • 除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继。
  • 树是递归定义的。

 注意:树形结构中,子树之间不能有交集,否则就不是树形结构,那样可能是图了,后续还会学习。

1.2树的相关概念

 节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的为6
叶节点或终端节点:度为0的节点称为叶节点; 如上图:B、C、H、I...等节点为叶节点
非终端节点或分支节点:度不为0的节点; 如上图:D、E、F、G...等节点为分支节点
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点孩子节点或子节点:个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节点
兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点
树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
树的高度或深度:树中节点的最大层次; 如上图:树的高度为4
堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:H、I互为兄弟节点
节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
森林:由m(m>0)棵互不相交的树的集合称为森林;

1.3树的表示

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既要保存值域,也要保存结点和结点之间的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等。我们这里就简单的了解其中最常用的孩子兄弟表示法。

 typedef int DataType;
struct Node
{
    struct Node* firstchild;   //第一个孩子节点
    struct Node* pnextbrother;  //指向其下一个兄弟节点
    DataType data;                //结点中的数据域
};

 

1.4树在实际中的运用(表示文件系统的目录树结构)

Linux中的文件目录就是按照一种树形结构来实现的。

2.二叉树的概念与结构

2.1概念

一棵二叉树是结点的一个有限集合,该集合:

  • 或者为空
  • 由一个根节点加上两棵别称为左子树和右子树的二叉树组成

 从上图可以明显看出:

  •  二叉树不存在度大于2的结点
  •  二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
  • 注意:对于任意的二叉树都是由以下几种情况复合而成的:

2.2现实中的二叉树

简直是大自然的奇迹,相信当我们程序员看到这样一颗树,呼之欲出的就是二叉树啦。 

2.3特殊的二叉树

  1. 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是 2^k-1,则它就是满二叉树。
  2. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

 

2.4二叉树的性质

1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有 2^(i-1)个结点.
2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2^h-1.
3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为n2,则有 n0=n2 +1
4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=log2(n+1)
是log以2为底n+1的对数。
5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的结点有:

  • 若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
  • 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
  • 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子

1. 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( )
A 不存在这样的二叉树
B 200
C 198
D 199
2.下列数据结构中,不适合采用顺序存储结构的是( )
A 非完全二叉树
B 堆
C 队列
D 栈
3.在具有 2n 个结点的完全二叉树中,叶子结点个数为( )
A n
B n+1
C n-1
D n/2
4.一棵完全二叉树的节点数位为531个,那么这棵树的高度为( )
A 11
B 10
C 8
D 12
5.一个具有767个节点的完全二叉树,其叶子节点个数为()
A 383
B 384
C 385
D 386
答案:
1.B
2.A
3.A
4.B
5.B

2.5二叉树的存储结构

二叉树一般可以使用两种存储方式,一种是顺序存储、一种是链式存储。

2.5.1顺序存储

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。

而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

2.5.2链式存储

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链,后面课程学到高阶数据结构如红黑树等会用到三叉链。

 

 typedef int BTDataType;
// 二叉链
struct BinaryTreeNode
{
    struct BinTreeNode* pLeft; // 指向当前节点左孩子
    struct BinTreeNode* pRight; // 指向当前节点右孩子
    BTDataType data; // 当前节点值域
};
// 三叉链
struct BinaryTreeNode
{
    struct BinTreeNode* pParent; // 指向当前节点的双亲
    struct BinTreeNode* pLeft; // 指向当前节点左孩子
    struct BinTreeNode* pRight; // 指向当前节点右孩子
    BTDataType data; // 当前节点值域
};

3.二叉树的顺序结构及其实现代码

3.1二叉树的顺序结构

普通的二叉树不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

3.2堆的概念及结构

如果有一个关键码的集合K = { k0,k1 ,k2 ,…,kn-1 },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2*i+1且 Ki<=K2*i+2  (Ki >= K2*i+1且 Ki>=K2*i+2,K后内容均为下标 ) i = 0,1,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
2.已知小根堆为8,15,10,21,34,16,12,删除关键字 8 之后需重建堆,在此过程中,关键字之间的比较次数是()。
A 1
B 2
C 3
D 4
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)
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]


选择题答案


1.A
2.C
3.C
4.C

3.3堆的实现

3.3.1堆的调整算法

向下调整

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。

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

 

 向下调整算法代码实现

void Swap(HPDatetype* pa, HPDatetype* pb)
{
	HPDatetype tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
void AdjustDown(HPDatetype* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)
	{
		//若假设的左孩子小,若假设是错的,更新一下
		if (child + 1 < size && a[child + 1] < a[child])
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = child * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

 向上与向下调整算法类似。

void Swap(HPDatetype* pa, HPDatetype* pb)
{
	HPDatetype tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
void AdjustUp(HPDatetype* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}

}

3.3.2堆的创建

下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根节点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆。

int a[] = {1,5,3,8,7,6}; 

 

3.3.3堆建时间复杂度

因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明(时间复杂度本来看的就是近似值,多几个节点不影响最终结果):

故建堆的时间复杂度为O(n)。 

3.3.4堆的插入

先插入一个数到数组的尾上,再进行向上调整算法,直到满足堆。

代码实现

void HeapPush(HP* php, int x)
{
	assert(php);
	if (php->capacity == php->size)
	{
		int newcapacity = php->capacity == 0 ? 4 : sizeof(php->a) * 2;
		HPDatetype * tmp = (HPDatetype*)realloc(php->a, newcapacity*sizeof(HPDatetype));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}
	php->a[php->size] = x;
	php->size++;
	
	AdjustUp(php->a, php->size - 1);
}

3.3.5堆的删除

删除堆是删除堆顶的数据,将堆顶的数据跟最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。

代码实现

void HeapPop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;
	AdjustDown(php->a, php->size, 0);
}

3.3.6堆的代码实现

Heap.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include<time.h>

typedef int HPDatetype;

typedef struct Heap
{
	int* a;
	int size;
	int capacity;
}HP;

//堆的初始化
void HeapIint(HP* php);

//堆的销毁
void HeapDestroy(HP* php);

//堆的插入
void HeapPush(HP* php, int child);

//堆的删除
void HeapPop(HP* php);

//取堆顶元素
HPDatetype HeapTop(HP* php);

//堆的数据个数
int HeapSize(HP* php);

//堆的判空
bool HeapEmpty(HP* php);

Heap.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"Heap.h"

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

void HeapDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->capacity = 0;
	php->size = 0;
}
void Swap(HPDatetype* pa, HPDatetype* pb)
{
	HPDatetype tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
void AdjustUp(HPDatetype* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}

}
void HeapPush(HP* php, int x)
{
	assert(php);
	if (php->capacity == php->size)
	{
		int newcapacity = php->capacity == 0 ? 4 : sizeof(php->a) * 2;
		HPDatetype * tmp = (HPDatetype*)realloc(php->a, newcapacity*sizeof(HPDatetype));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}
	php->a[php->size] = x;
	php->size++;
	
	AdjustUp(php->a, php->size - 1);
}
void AdjustDown(HPDatetype* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)
	{
		//若假设的左孩子小,若假设是错的,更新一下
		if (child + 1 < size && a[child + 1] < a[child])
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = child * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void HeapPop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;
	AdjustDown(php->a, php->size, 0);
}

HPDatetype HeapTop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	return php->a[0];
}

int HeapSize(HP* php)
{
	assert(php);

	return php->size;
}

bool HeapEmpty(HP* php)
{
	assert(php);

	return php->size == 0;
}

3.4堆的应用

3.4.1 堆排序

1.建堆

根据升序和降序来决定是建大堆还是建小堆,

升序建大堆,反之建小堆。

2.利用堆删除思想来进行排序

 代码实现堆排序

void HeapSort(int* a, int n)
{
	//升序
	//建大堆
	//降序
	//建小堆
	/*for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}*/
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}
	//选数
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
}

3.4.2 TOP-K问题

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:

1. 用数据集合中前K个元素来建堆


前k个最大的元素,则建小堆
前k个最小的元素,则建大堆


2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素


将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

代码实现: 

void CreateNDate()
{
	// 造数据
	int n = 10000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	for (size_t i = 0; i < n; ++i)
	{
		int x = rand() % 1000000;
		fprintf(fin, "%d\n", x);
	}

	fclose(fin);
}

void PrintTopK(int k)
{
	FILE* fout = fopen("data.txt", "r");
	if (fout == NULL)
	{
		perror("fopen fail");
		return;
	}
	//建立k个数的小堆
	int* minheap = (int*)malloc(sizeof(int) * k);
	if (minheap == NULL)
	{
		perror("malloc fail");
		return;
	}
	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &minheap[i]);
		AdjustUp(minheap,i);
	}
	int x = 0;
	while (fscanf(fout, "%d", &x) != EOF)
	{
		if (x > minheap[0])
		{
			minheap[0] = x;
			AdjustDown(minheap, k, 0);
		}
	}
	for (int i = 0; i < k; i++)
	{
		printf("%d ", minheap[i]);
	}
	printf("\n");

	free(minheap);
	minheap = NULL;
	fclose(fout);
}

int main()
{
	int k = 5;
	CreateNDate();
	PrintTopK(k);
	return 0;
}

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

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

相关文章

Microsoft edge@常见问题@由组织管理@策略组@版本问题

文章目录 本地edge浏览器由组织管理功能受限检查例:侧边栏功能被禁用解出限制(删除相关注册表条目)解除限制检查refs 页面加载问题this page having a problem 禁止edge更新refs 版本回滚 本地edge浏览器由组织管理功能受限检查 浏览器输入edge://management/检查通过修改注册表…

【数据仓库与联机分析处理】多维数据模型

目录 一、数据立方体 二、数据模型 &#xff08;一&#xff09;星形模型 &#xff08;二&#xff09;雪花模式 &#xff08;三&#xff09;事实星座模式 三、多维数据模型中的OLAP操作 &#xff08;一&#xff09;下钻 &#xff08;二&#xff09;上卷 &#xff08;三…

宏电股份5G RedCap终端产品助力深圳极速先锋城市建设

12月26日&#xff0c;“全城全网&#xff0c;先锋物联”深圳移动5G-A RedCap助力深圳极速先锋城市创新发布会举行&#xff0c;宏电股份携一系列5G RedCap终端产品应邀参与创新发布会&#xff0c;来自全国5G生态圈的各界嘉宾、专家学者济济一堂&#xff0c;共探信息化数字化创新…

mysql之视图mysql连接案例索引

文章目录 一、视图1.1 含义1.2 操作1.2.1 创建视图1.2.2 视图的修改1.2.3 删除视图1.2.4 查看视图 二、连接案例01)查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数02)查询同时存在" 01 "课程和" 02 "课程的情况03&#xff0…

ios 裁剪拼装图片

//1.获取图片UIImage *image [UIImage imageNamed:"123.jpg"];//处理图片//2.获取图片的长度long length image.size.width/4;//3.图片顶点索引long indices[] {length * 2,length,//右 right0,length,//左 leftlength,0,//上 toplength,length * 2,//底 bottomle…

Rustdesk打开Win10 下客户端下面服务不会自启,显示服务未运行

环境: Rustdesk1.19 问题描述: Rustdesk打开Win10 下客户端下面服务不会自启,显示服务未运行 解决方案: 1.查看源代码 pub async fn start_all() {crate::hbbs_http::sync::start();let mut nat_tested = false;check_zombie()

SwinTransformer

patch embedding (b,3,224,224)->(b,N,96) N:patch数量 为每个stage中的每个Swin Transformer block设置drop_rate&#xff0c;根据设置[2,2,6,2]&#xff0c;每个Swin Transformer block的drop_path为0~0.1等间距采样的12个小数&#xff0c;参数0.1也可以更改。还有个drop参…

网络安全红队常用的攻击方法及路径

一、信息收集 收集的内容包括目标系统的组织架构、IT资产、敏感信息泄露、供应商信息等各个方面&#xff0c;通过对收集的信息进行梳理&#xff0c;定位到安全薄弱点&#xff0c;从而实施下一步的攻击行为。 域名收集 1.备案查询 天眼查爱企查官方ICP备案查询 通过以上三个…

数据矩阵集成可提高印刷电路板识别的准确性

在复杂的印刷电路板 (PCB) 世界中&#xff0c;准确的电路板元件识别对于简化故障排除至关重要。它确保电子设备高效运行。 本文将探讨数据矩阵码在提高 PCB 零件识别效率方面的作用。数据矩阵码提供了一种简单的解决方案来编码和解码与 PCB 组件相关的信息&#xff0c;在简化识…

安卓Android Studioy读写NXP ICODE2 15693标签源码

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?spma1z10.5-c-s.w4002-21818769070.11.4391789eCLwm3t&id615391857885 <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xm…

『C++成长记』日期类的实现

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;C &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、日期类的实现 &#x1f4d2;1.1日期类功能 &#x1f4d2;1.2拷贝日期 &#…

C++面试宝典第13题:计算餐厅账单

题目 假如你是一家餐厅的收银员,需要编写一个程序来计算顾客的账单。程序应该能够接受顾客点的菜品和数量,并根据菜品的单价计算出总价。另外,程序还应该能够处理折扣和优惠券,并输出最终的账单金额。 解析 这道题主要考察应聘者使用面向对象的设计方法来解决实际问题的能力…

基于旗鱼算法优化的Elman神经网络数据预测 - 附代码

基于旗鱼算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于旗鱼算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于旗鱼优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针…

Pandas DataFrame中将True/False映射到1/0

在本文中&#xff0c;我们将看到如何在Pandas DataFrame中将True/False映射到1/0。True/False到1/0的转换在执行计算时至关重要&#xff0c;并且可以轻松分析数据。 1. replace方法 在这个例子中&#xff0c;我们使用Pandas replace()方法将True/False映射到1/0。在这里&…

网络知识-以太网技术的发展及网络设备

目 录 一、背景介绍 &#xff08;一&#xff09;网络技术的时代 &#xff08;二&#xff09;以太网技术脱颖而出 二、以太网的工作原理 &#xff08;一&#xff09;、载波侦听多路访问&#xff08;CSMA/CD&#xff09; 1、数据发送流程 2、发送过程解析 3、…

Mathtype7.4安装与嵌入WPS

文章目录 Mathtype安装教程&#xff08;7.4&#xff09;Mathtype简介Mathtype下载安装软件下载软件安装运行MathType.exe运行注册表 Mathtype嵌入wps Mathtype安装教程&#xff08;7.4&#xff09; Mathtype简介 MathType是一款强大的数学公式编辑器&#xff0c;适用于教育教…

【Sublime Text】| 01——下载安装注册

系列文章目录 【Sublime Text】| 01——下载软件安装并注册 【Sublime Text】| 02——常用插件安装及配置 失败了也挺可爱&#xff0c;成功了就超帅。 文章目录 前言1. 下载2. 安装3. 注册3.1 通过修改应用程序注册3.2 通过替换应用程序注册 感谢 前言 轻量代码编辑器有很多 之…

Python课程设计基于python的人脸识别佩戴口罩系统设计

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;python口罩 获取完整论文报告源码源文件 1 研究背景与意义 新型冠状病毒展现出全球化流行和蔓延的趋势&#xff0c;这提醒我们&#xff1a;传染病防治在今后相当长时间内仍是疾病预测控制工作的重点。戴口罩是预防呼吸道…

Linux|服务器|简单记录备忘VMware虚拟机开启桌面失败报错:VMware: No 3D enabled (0, Success).的解决

一&#xff0c; VMware虚拟机 Linux操作系统&#xff0c;centos7版本&#xff0c;安装完桌面后&#xff0c;执行startx 命令后 &#xff0c;报错&#xff1a;VMware: No 3D enabled (0, Success). 桌面没有启动成功 完整日志输出如下&#xff1a; [rootnode4 ~]# startx x…

超实用的测试万能法则 —— 帕累托分析!

20/80原则来源于意大利经济学家维弗雷多•帕累托&#xff08;Villefredo Pareto&#xff09;提出的财富占比帕累托原则&#xff1a;80%的财富是掌握在20%的人手中的&#xff0c;而余下的80%的人只占那剩余的20%财富&#xff0c;而后这个理论延伸为&#xff1a;至关重要的少数和…