數據結構之二叉樹的超詳細講解(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.pswp.cn/web/13824.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/13824.shtml
英文地址,請注明出處:http://en.pswp.cn/web/13824.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

電腦卸載linux安裝windows后每次開機都出現grub

原因分析 這是因為電腦硬盤中還存在linux系統的引導程序&#xff0c;并且啟動順序還在windows之前&#xff0c;有時候通過bios根本找不到它的存在&#xff0c;以至于每次windows開機出現grub之后都要輸入exit退出linux的引導之后才能使得電腦進入windows&#xff0c;這個有時會…

算法訓練營第三十六天 | LeetCode 1005 K次取反后最大化的數組、LeetCode 134 加油站

LeetCode 1005 K次組飯后最大化的數組 這題貪的主要是數值最大化。如果K > 負數個數&#xff0c;我們就先將負數全部轉換成它的相反數&#xff0c;并將K--&#xff0c;之后K剩余的值可以對2取模&#xff0c;為0的話直接得出最后結果&#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 是一個開源的分布式版本控…

Java - Stream流式編程

Stream流式操作 Stream流式操作&#xff0c;就是學習java.util.stream包下的API&#xff0c;Stream不同于java的輸入輸出流&#xff0c;是實現對集合&#xff08;Collection&#xff09;的復雜操作&#xff0c;例如查找、替換、過濾和映射數據等&#xff0c;集合是一種靜態的數…

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刪除不…

CGAL 點云生成高程模型數據(DSM)

點云生成高程模型 一、什么是DSM?二、C++代碼三、結果可視化一、什么是DSM? DSM(Digital Surface Model)是一種數字高程模型,通常用于描述地表地形的數字化表示。它是由一系列離散的高程數據點組成的三維地形模型,其中每個點都具有其相應的高程值。 ??DSM主要用于獲取和…

宿舍管理系統--畢業設計

畢業設計&#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;可以生成更符合實際研發場景的優質代碼。…

自動化測試里的數據驅動和關鍵字驅動思路的理解

&#x1f345; 視頻學習&#xff1a;文末有免費的配套視頻可觀看 &#x1f345; 點擊文末小卡片&#xff0c;免費獲取軟件測試全套資料&#xff0c;資料在手&#xff0c;漲薪更快 初次接觸自動化測試時&#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個可配置閾值檢測…