数据结构之二叉树的超详细讲解(2)--(堆的概念和结构的实现,堆排序和堆排序的应用)

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

数据结构之二叉树的超详细讲解(2)--(堆的概念和结构的实现,堆排序和堆排序的应用)

收录于专栏【数据结构初阶】
本专栏旨在分享学习数据结构学习的一点学习笔记,欢迎大家在评论区交流讨论💌

之前发布过数据结构之二叉树的超详细讲解(1)--(树和二叉树的概念和结构) ,今天重点讲解堆的概念和结构的实现,堆排序和堆排序的应用,感兴趣的宝子们赶紧点赞收藏起来吧!💓💓💓

目录

1.二叉树的顺序结构及实现 

1.1二叉树的顺序结构

1.2 堆的概念及结构 

1.3堆算法的实现

1.3.1堆结构的实现

1.3.2堆操作函数 

1.3.2.1堆的初始化

1.3.2.2堆的销毁

1.3.2.3堆顶和堆尾元素的交换

1.3.2.4堆的调整算法

1.3.2.4.1向上调整建堆(以小根堆为例)

1.3.2.4.2向下调整建堆(以小根堆为例)

1.3.2.5数据进堆

1.3.2.6堆顶元素出堆

1.3.2.7输出堆顶元素

1.3.2.8堆的判空

练习:

2.堆排序

2.1向上调整建堆

2.1.1小根堆

2.1.2大顶堆

2.2向下调整建堆

2.2.1小根堆

2.2.2大根堆 

2.3堆排序的完整代码参考:

2.4建堆的时间复杂度 

2.4.1向下调整建堆的时间复杂度: 

2.4.1向上调整建堆的时间复杂度: 

2.5堆排序的应用-- TOP-K问题

方法一:

方法二:

 参考代码:

Heap.h:

Heap.c:

text.c:


1.二叉树的顺序结构及实现 

1.1二叉树的顺序结构

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

1.2 堆的概念及结构 

如果有一个关键码的集合K = { k0,k1,k2,,,,,,,,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: ki<=k2*i 且 ki <= k2*i+2 (k >= k2*i+1 且ki >= k2*i+2) i = 0,1, 2…,则称为小堆(或大堆)。将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。

这里运用了二叉树性质五:

堆的性质:

堆中某个结点的值总是不大于或不小于其父结点的值;

堆总是一棵完全二叉树。 

如下图所示: 

1.3堆算法的实现

1.3.1堆结构的实现

之前说到过,堆就是完全二叉树, 把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,所以我们这里使用动态数组的方式建堆,类似于使用动态数组构建顺序表

顺序表的构建和基本操作-CSDN博客

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

 a就是我们的一个动态数组

size是我们堆中的元素个数

capacity是我们堆的容量,方便后面动态开辟空间

HPDataType方便后面我们进行类型的修改,比如我们不需要整形了,而是char类型,直接修改HPDataType就可以了

1.3.2堆操作函数 

//堆顶和堆尾元素的交换
void Swap(HPDataType* p1, HPDataType* p2);
//向上调正算法
void AdjustUp(HPDataType* a, int child);
//向下调整算法
void AdjustDown(HPDataType* a, int n, int parent);
//堆的初始化
void HPInit(HP* php);
//堆的销毁
void HPDestroy(HP* php);
//数据近堆
void HPPush(HP* php, HPDataType x);
//堆顶元素出堆
void HPPop(HP* php);
//输出队顶元素
HPDataType HPTop(HP* php);
//堆的判空
bool HPEmpty(HP* php);
1.3.2.1堆的初始化
void HPInit(HP* php)
{assert(php);php->a = NULL;php->size = php->capacity = 0;
}
1.3.2.2堆的销毁
void HPDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = php->capacity = 0;
}

注意:

free释放掉a之后,还需要将a置为NULL 

1.3.2.3堆顶和堆尾元素的交换
void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}

为后面的调整算法算法埋下铺垫 

1.3.2.4堆的调整算法
1.3.2.4.1向上调整建堆(以小根堆为例)

如下图所示(以小根堆为例):

我们将新插入的数据不断的与它的parent节点进行比较 

代码展示:

void AdjustUp(HPDataType* a, int child)
{// 初始条件// 中间过程// 结束条件int parent = (child - 1) / 2;//while (parent >= 0)while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

注意:

根据我们之前学过的二叉树的性质,左child可以通过(child-1)/2和右孩子(child-2)/2来找到它的母亲节点,因为编译器的向下取整,所以我们直接使用int parent = (child - 1) / 2;来解决,不需要判断左右孩子

如下图 :

这里我们的循环停止条件有两种:

第一种:while (parent >= 0) 

第一种需要注意:当我们的parent = 0时,假设当时child还是比parent小,child  = parent,parent = (child - 1) / 2;还是会进入下一次循环,此时child = parent = 0,由于存在if的判断循环会结束,不会造成死循环现象,属于歪打正着

第二种就严谨很多:

第二种采用child作为循环条件的判断,当我们的child大于0,就会一直进行交换直到child等于0时,即为堆顶元素时,循环停止

1.3.2.4.2向下调整建堆(以小根堆为例)


 

注意:

向下调整建堆需要以27为根的左右子树都满足小堆的性质,只有根节点不满足.因此只需要将根节点往下调,往下调时需要与最小的那个值进行比较

代码展示:

void AdjustDown(HPDataType* a, int n, int parent)
{// 先假设左孩子小int child = parent * 2 + 1;while (child < n)  // child >= n说明孩子不存在,调整到叶子了{// 找出小的那个孩子if (child + 1 < n && a[child + 1] < a[child]){++child;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

这里我们使用假设法,先假设左孩子小,然后进入循环,进入循环后进行判断,因为我们需要将较小的孩子与我们的parent进行交换,如果它本来就小,那就直接跳过,然后交换parent和child,如图所示:

1.3.2.5数据进堆

这里需要注意,数据进堆时,我们需要对进堆的数据进行调整,这样我们进堆结束后,即建堆完毕

代码展示:

void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a, newcapacity * sizeof(HPDataType));if (tmp == NULL){perror("realloc fail");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}
1.3.2.6堆顶元素出堆
void HPPop(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);
}

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。这样我们向下调整时两边都是小根堆,满足向下调整的条件

1.3.2.7输出堆顶元素
HPDataType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}
1.3.2.8堆的判空
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

练习:

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]

解析:

第一题:我们上面说到过,堆其实就是完全二叉树,所以我们直接构建完全二叉树:

只有A选项满足大堆的需求

第二题:

第三题:

只有c选项满足大顶堆的要求

第四题:

删除后,堆的调整如下:

2.堆排序

2.1向上调整建堆

2.1.1小根堆

	for (size_t i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]);}

 对每一次插入堆中的数据进行调整建堆

测试数据:

    int a[] = { 4,2,8,1,5,6,9,7,3,2,23,55,232,66,222,33,7,1,66,3333,999 }; 

	while (!HPEmpty(&hp)){printf("%d ", HPTop(&hp));//a[i++] = HPTop(&hp);HPPop(&hp);}printf("\n");

根据小根堆的性质:它的堆顶元素一定是数组中最小的数据,我们将堆顶数据输出,在重新建堆,直到堆中没有数据,这样就可以实现堆排序 

输出结果:

2.1.2大顶堆

建立大顶堆只需要改变我们之前写的向上向下调整代码:

向上调整代码:

void AdjustUp(HPDataType* a, int child)
{// 初始条件// 中间过程// 结束条件int parent = (child - 1) / 2;//while (parent >= 0)while (child > 0){//如果孩子比parent大if (a[child] > a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

再向上调整代码中,我们只需要将if的判断改为>就可以了 

向下调整代码:

void AdjustDown(HPDataType* a, int n, int parent)
{// 先假设左孩子小int child = parent * 2 + 1;while (child < n)  // child >= n说明孩子不存在,调整到叶子了{// 找出小的那个孩子//找出大的那个孩子if (child + 1 < n && a[child + 1] > a[child]){++child;}//如果孩子比母亲大if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

 再向下调整代码中,我们需要调整两处,一个是我们需要找大的那个孩子,将<改为>,还有我们交换的条件需要孩子比母亲大,也是将<改为>

测试数据和代码不变:

所以你只需要会小根堆,大顶堆只需要改变三个地方 

2.2向下调整建堆

再实际应用中,我们建堆并不会使用向上调整建堆,因为时间复杂度不够低,但向上调整建堆更容易理解,大家可以根据自己的情况进行选择,这里我还是推荐向下调整建堆

	for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);}

 

我们这里第一个非叶子节点即最后一个节点的母亲节点:

也就是(n - 1 - 1) / 2,如图所示:

2.2.1小根堆

测试数据    int a[] = { 4,2,8,1,5,6,9,7,2,7,9 };

2.2.2大根堆 

数据和小根堆一样:

2.3堆排序的完整代码参考:

void HeapSort(int* a, int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);}int end = n - 1;while (end > 0){printf("%d ", a[0]);Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}int main()
{int a[] = { 4,2,8,1,5,6,9,7,2,7,9 };HeapSort(a, sizeof(a) / sizeof(int));return 0;
}

2.4建堆的时间复杂度 

 我们上面说到过,向下建堆的时间复杂度是优于向上建堆的,这里我们具体分析一下:

2.4.1向下调整建堆的时间复杂度: 

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

这里我们是向下调整建堆,是从第一个非叶子节点开始一直到第一个节点的向下调整,如下图所示: 

根据上面的图,我们可以很简单的得到下面的等式: 

再根据我们高中学过的错位相减法,进一步化简: 

因此:向下建堆的时间复杂度为O(N)。 

2.4.1向上调整建堆的时间复杂度: 

因此向上调整建堆的时间复杂度为N*logN 

总结:

 向下调整:节点数量少的层*调整次数多的层 

 向上调整:节点数量多的层*调整次数多的层

 向下建堆的时间复杂度为O(N)。 

上调整建堆的时间复杂度为N*logN 

2.5堆排序的应用-- TOP-K问题

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。

比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。

再比如:大家都玩过王者荣耀吧,金标或者国标都需要取前100名玩家,再几亿玩家中找出战力最高的100名玩家,如果你用快排的话,电脑估计要转冒烟了,但TOP-K可以很好的解决这个问题

方法一:

建立一个N个数的大堆,TOP K次 

这个方法是可行的,不过不够完美,因为再TOP K问题中,N往往是很大的,这样你建堆的一个内存就很大,算法的空间损耗会很大 

方法二:

用前K个数建一个小堆

 

 建堆的时间复杂度为O(K),然后还进行了(N-K)比较,所以总的时间复杂度为O(K + (N-K)*log(K)),假设是最坏的情况,每一次比较都需要向下调整,因为K是远小于N的,所以K,logK可以忽略不记,总时间复杂度为O(N),也就是上亿的数据,也能再秒之内完成 

测试方法二:

创建数据:

void CreateNDate()
{// 造数据int n = 100000;srand(time(0));const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (int i = 0; i < n; ++i){int x = (rand() + i) % 10000000;fprintf(fin, "%d\n", x);}fclose(fin);
}

输出结果:

创造一百完个随机数据

TOP-K求解:

void TestHeap3()
{int k;printf("请输入k>:");scanf("%d", &k);int* kminheap = (int*)malloc(sizeof(int) * k);if (kminheap == NULL){perror("malloc fail");return;}const char* file = "data.txt";FILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen error");return;}// 读取文件中前k个数for (int i = 0; i < k; i++){fscanf(fout, "%d", &kminheap[i]);}// 建K个数的小堆for (int i = (k - 1 - 1) / 2; i >= 0; i--){AdjustDown(kminheap, k, i);}// 读取剩下的N-K个数int x = 0;while (fscanf(fout, "%d", &x) > 0){if (x > kminheap[0]){kminheap[0] = x;AdjustDown(kminheap, k, 0);}}printf("最大前%d个数:", k);for (int i = 0; i < k; i++){printf("%d ", kminheap[i]);}printf("\n");
}

手动更改十个数据大于10000000的数,查看结果:

 输出结果:

 参考代码:

Heap.h:

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;
//堆顶和堆尾元素的交换
void Swap(HPDataType* p1, HPDataType* p2);
//向上调正算法
void AdjustUp(HPDataType* a, int child);
//向下调整算法
void AdjustDown(HPDataType* a, int n, int parent);
//堆的初始化
void HPInit(HP* php);
//堆的销毁
void HPDestroy(HP* php);
//数据近堆
void HPPush(HP* php, HPDataType x);
//堆顶元素出堆
void HPPop(HP* php);
//输出队顶元素
HPDataType HPTop(HP* php);
//堆的判空
bool HPEmpty(HP* php);

Heap.c:

#define _CRT_SECURE_NO_WARNINGS 1#include"Heap.h"void HPInit(HP* php)
{assert(php);php->a = NULL;php->size = php->capacity = 0;
}void HPDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = php->capacity = 0;
}void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPDataType* a, int child)
{// 初始条件// 中间过程// 结束条件int parent = (child - 1) / 2;//while (parent >= 0)while (child > 0){//如果孩子比parent大if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a, newcapacity * sizeof(HPDataType));if (tmp == NULL){perror("realloc fail");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}void AdjustDown(HPDataType* a, int n, int parent)
{// 先假设左孩子小int child = parent * 2 + 1;while (child < n)  // child >= n说明孩子不存在,调整到叶子了{// 找出小的那个孩子//找出大的那个孩子if (child + 1 < n && a[child + 1] < a[child]){++child;}//如果孩子比母亲大if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}// logN
void HPPop(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);
}HPDataType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

text.c:

#define _CRT_SECURE_NO_WARNINGS 1#include <time.h>
#include"Heap.h"void TestHeap1()
{int a[] = { 4,2,8,1,5,6,9,7,3,2,23,55,232,66,222,33,7,1,66,3333,999 };HP hp;HPInit(&hp);for (size_t i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]);}int i = 0;while (!HPEmpty(&hp)){printf("%d ", HPTop(&hp));//a[i++] = HPTop(&hp);HPPop(&hp);}printf("\n");// 找出最大的前k个/*int k = 0;scanf("%d", &k);while (k--){printf("%d ", HPTop(&hp));HPPop(&hp);}printf("\n");*/HPDestroy(&hp);
}// 堆排序    O(N*logN)
// 冒泡排序  O(N^2) 
void HeapSort(int* a, int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);}int end = n - 1;while (end > 0){printf("%d ", a[0]);Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}void CreateNDate()
{// 造数据int n = 100000;srand((unsigned int)time(NULL));const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (int i = 0; i < n; ++i){int x = (rand() + i) % 10000000;fprintf(fin, "%d\n", x);}fclose(fin);
}void TestHeap3()
{int k;printf("请输入k>:");scanf("%d", &k);int* kminheap = (int*)malloc(sizeof(int) * k);if (kminheap == NULL){perror("malloc fail");return;}const char* file = "data.txt";FILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen error");return;}// 读取文件中前k个数for (int i = 0; i < k; i++){fscanf(fout, "%d", &kminheap[i]);}// 建K个数的小堆for (int i = (k - 1 - 1) / 2; i >= 0; i--){AdjustDown(kminheap, k, i);}// 读取剩下的N-K个数int x = 0;while (fscanf(fout, "%d", &x) > 0){if (x > kminheap[0]){kminheap[0] = x;AdjustDown(kminheap, k, 0);}}printf("最大前%d个数:", k);for (int i = 0; i < k; i++){printf("%d ", kminheap[i]);}printf("\n");
}int main()
{//CreateNDate();TestHeap3();return 0;
}

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

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

相关文章

电脑卸载linux安装windows后每次开机都出现grub

原因分析 这是因为电脑硬盘中还存在linux系统的引导程序&#xff0c;并且启动顺序还在windows之前&#xff0c;有时候通过bios根本找不到它的存在&#xff0c;以至于每次windows开机出现grub之后都要输入exit退出linux的引导之后才能使得电脑进入windows&#xff0c;这个有时会…

Python | Leetcode Python题解之第108题将有序数组转换为二叉搜索树

题目&#xff1a; 题解&#xff1a; class Solution:def sortedArrayToBST(self, nums: List[int]) -> TreeNode:def helper(left, right):if left > right:return None# 选择任意一个中间位置数字作为根节点mid (left right randint(0, 1)) // 2root TreeNode(nums…

纯血鸿蒙APP实战开发——边缓存边播放案例

介绍 OhosVideoCache是一个支持边播放边缓存的库&#xff0c;只需要将音视频的url传递给OhosVideoCache处理之后再设置给播放器&#xff0c; OhosVideoCache就可以一边下载音视频数据并保存在本地&#xff0c;一边读取本地缓存返回给播放器&#xff0c;使用者无需进行其他操作…

NDIS小端口驱动(五)

在需要的时候&#xff0c;我们也许需要NDIS微型端口程序信息&#xff0c;下面会从多个方面来讨论如何查询NDIS微型端口驱动。 查询无连接微型端口驱动程序 若要查询无连接微型端口驱动程序维护的 OID&#xff0c;绑定协议调用 NdisOidRequest 并传递 一个NDIS_OID_REQUEST 结…

Mac 安装 git

文章目录 前言一、介绍二、下载三、验证四、配置五、Git常用命令六、git提交和撤销工作流程代码提交和提交同步代码撤销和撤销同步 FAQ1.homebrew 下载解决方法一&#xff08;强烈推荐&#xff09;&#xff1a;解决方法二&#xff1a; 总结 前言 Git 是一个开源的分布式版本控…

LeetCode547省份数量

题目描述 有 n 个城市&#xff0c;其中一些彼此相连&#xff0c;另一些没有相连。如果城市 a 与城市 b 直接相连&#xff0c;且城市 b 与城市 c 直接相连&#xff0c;那么城市 a 与城市 c 间接相连。省份 是一组直接或间接相连的城市&#xff0c;组内不含其他没有相连的城市。给…

第十一章 文件及IO操作

第十一章 文件及IO操作 文件的概述及基本操作步骤 文件&#xff1a; 存储在计算机的存储设备中的一组数据序列就是文件不同类型的文件通过后缀名进行区分 文本文件&#xff1a;由于编码格式的不同&#xff0c;所占磁盘空间的字节数不同(例如GBK编码格式中一个中文字符占2字…

cesium绘制三角网可视化及mesh网格数据解析

可视化运行效果(水质污染扩散) 实现运行效果 术语 Mesh网格数据解析 Mesh&#xff08;网格&#xff09;在不同领域有不同的应用和定义。在计算机网络中&#xff0c;Mesh网络指的是一种无中心的网状结构&#xff0c;每个节点都与其他节点相连。而在3D计算机图形学中&#…

云原生Kubernetes: K8S 1.26版本 部署KubeSphere

目录 一、实验 1.环境 2.K8S 1.26版本部署HELM 3.K8S 1.26版本 部署KubeSphere 4.安装KubeSphere DevOps 二、问题 1.如何安装Zadig 2.扩展插件Zadig安装失败 3.calico 如何实现不同node通信 4.如何清除docker占用的磁盘空间 5.如何强制删除资源 6.namespace删除不…

宿舍管理系统--毕业设计

毕业设计&#x1f4bc;MD5加密&#x1f512;SSM框架&#x1f3a8;Layui框架&#x1f384; 实现功能 管理员的登录与登出 管理员,班级,学生,宿舍&#xff0c;卫生&#xff0c;访客各模块增删改查 个别模块关联查询 各个模块数据导出Excel 一些截图

[4]CUDA中的向量计算与并行通信模式

CUDA中的向量计算与并行通信模式 本节开始&#xff0c;我们将利用GPU的并行能力&#xff0c;对其执行向量和数组操作讨论每个通信模式&#xff0c;将帮助你识别通信模式相关的应用程序&#xff0c;以及如何编写代码 1.两个向量加法程序 先写一个通过cpu实现向量加法的程序如…

软件设计:基于 python 代码快速生成 UML 图

1. 官方文档 PlantUML Language Reference Guide Comate | 百度研发编码助手 百度 Comate (Coding Mate Powered by AI) 是基于文心大模型的智能代码助手&#xff0c;结合百度积累多年的编程现场大数据和外部优秀开源数据&#xff0c;可以生成更符合实际研发场景的优质代码。…

GBDT、XGBoost、LightGBM算法详解

文章目录 一、GBDT (Gradient Boosting Decision Tree) 梯度提升决策树1.1 回归树1.2 梯度提升树1.3 Shrinkage1.4 调参1.5 GBDT的适用范围1.6 优缺点 二、XGBoost (eXtreme Gradient Boosting)2.1 损失函数2.2 正则项2.3 打分函数计算2.4 分裂节点2.5 算法过程2.6 参数详解2.7…

oracle中insert all的用法

1、简述 使用insert into语句进行表数据行的插入&#xff0c;但是oracle中有一个更好的实现方式&#xff1a;使用insert all语句。 insert all语句是oracle中用于批量写数据的 。insert all分又为 无判断条件插入有判断条件插入有判断条件插入分为 Insert all when... 子句 …

利用 MongoDB Atlas 进行大模型语义搜索和RAG

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学. 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总合集&…

基于英飞凌BGT60LTR11AIP E6327芯片具低功耗的脉冲多普勒操作模式常用于汽车应用的雷达上

芯片特征&#xff1a; 60 GHz收发器MMIC&#xff0c;带一个发射器和一个接收器单元封装天线&#xff08;AIP&#xff09;&#xff08;6.73.30.56 mm3)低功耗的脉冲多普勒操作模式自主模式用于运动和运动方向的集成检测器运动检测信号的直接输出目标检测范围的15个可配置阈值检测…

Android14之Binder调试(二百一十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

2024年5月20日优雅草蜻蜓API大数据服务中心v2.0.4更新

v2.0.4更新 v2.0.4更新 2024年5月20日优雅草蜻蜓API大数据服务中心v2.0.4更新-增加ai绘画接口增加淘宝联想词接口底部增加联系方式 更新日志 底部增加联系方式 增加ai绘画接口 增加淘宝联想词接口 增加用户中心充值提示 用户中心内页颜色改版完成 截图 部分具体更新接口信…

【NLP】词性标注

词 词是自然语言处理的基本单位&#xff0c;自动词法分析就是利用计算机对词的形态进行分析&#xff0c;判断词的结构和类别。 词性&#xff08;Part of Speech&#xff09;是词汇最重要的特性&#xff0c;链接词汇和句法 词的分类 屈折语&#xff1a;形态分析 分析语&#…

k8s 1.24.x之后如果rest 访问apiserver

1.由于 在 1.24 &#xff08;还是 1.20 不清楚了&#xff09;之后&#xff0c;下面这两个apiserver的配置已经被弃用 了&#xff0c;简单的说就是想不安全的访问k8s是不可能了&#xff0c;所以只能走安全的访问方式也就是 https://xx:6443了&#xff0c;所以需要证书。 - --ins…