《數據結構初階》【番外篇:二路歸并的外排史詩】

【番外篇:多路歸并的外排史詩】目錄

  • 前言:
  • ---------------介紹---------------
  • 一、實際情景
  • 二、外部排序
    • 什么是外部排序?
  • 三、多路歸并排序
    • 什么是多路歸并排序?
  • ---------------實現---------------
  • 四、文件歸并
    • 文件二路歸并排序思路是什么?
    • 文件二路歸并排序怎么實現?
      • 頭文件:ExternalSort.h
      • 實現文件:ExternalSort.c
      • 主程序文件:Main.c
      • 運行結果

在這里插入圖片描述

往期《數據結構初階》回顧:
【時間復雜度 + 空間復雜度】
【順序表 + 單鏈表 + 雙向鏈表】
【順序表/鏈表 精選15道OJ練習】
【順序棧 + 鏈式隊列 + 循環隊列】
【鏈式二叉樹】
【堆 + 堆排序 + TOP-K】
【二叉樹 精選9道OJ練習】
【八大排序——群英薈萃】
【八大排序——巔峰決戰】
【番外篇:快速排序的前世今生】

前言:

(づ。????。)づ hi~ 小伙伴們久等啦!(????) 博主今天終于發布 【番外篇:多路歸并的外排史詩】 啦!?
特此聲明:博主并沒有 “跑路” 哦~~( ̄▽ ̄*)ゞ 這篇博客其實早就寫完了,只是特意等到端午節這個特別的日子發送~🎉
🎉今天不僅是端午節🐲,也是我們《數據結構初階》系列正式完結的日子!🥳
從博主發布的第一篇《數據結構初階》博客【時間復雜度 + 空間復雜度】到今天,不知不覺已經過去將近一個半月啦,時間過得好快!😭

這篇博客雖然篇幅不長(約 4k 字),但內容完整覆蓋了理論→實踐全流程~📖
博主相信,通過閱讀本文,你一定能熟練掌握 大文件外部排序 —— 二路歸并排序 的核心原理與實現!?(???。)?

---------------介紹---------------

一、實際情景

當待排序的數據量遠遠超過計算機內存容量時,直接使用常規的內部排序算法(例如:快速排序、歸并排序等,之前我們學習的八大排序都是內部排序)會面臨數據無法完整加載到內存的困境。

當數據無法一次性加載到內存中處理時,需要借助外部存儲設備(:硬盤、U 盤等),通過 內存與外存之間的多次數據交換 完成排序。

所以:我們就需要借助 外部排序 算法,通過協調內存外部存儲設備之間的數據交互,分階段完成排序任務。

二、外部排序

什么是外部排序?

外部排序(External Sorting):是一種處理 數據量遠超計算機內存容量 的排序技術。

外部排序的核心思想:

  • 將大規模數據拆分為多個可處理的小數據塊,先在內存中對每個數據塊進行排序生成有序歸并段
  • 再通過多路歸并等策略將這些有序段逐步合并,最終得到完整的有序數據集

這種方式有效突破了內存容量的限制,成為處理海量數據排序的關鍵技術手段。


一句話總結外部排序是內存不足時的「排序救星」

它通過「分割數據→內存排序→歸并合并」的流程,解決了傳統排序無法處理海量數據的問題,本質是一種「利用外存擴展內存能力」的工程化解決方案。


所以:下面我們就來了解一下外部排序的經典方法:多路歸并排序

三、多路歸并排序

什么是多路歸并排序?

多路歸并排序(Multi-way Merge Sort):是外部排序中常用的核心技術,用于解決「數據量遠超內存容量」時的排序問題。

  • 它的本質是 將多個有序子序列(歸并段)逐步合并成一個完整的有序序列
  • 它是傳統二路歸并排序的擴展,可同時合并K個有序序列,顯著減少歸并輪次

多路歸并排序核心原理與流程:

外部排序通常分為兩個階段:預處理階段(生成歸并段)歸并階段(合并有序段)

1. 預處理階段:生成初始歸并段

  • 步驟
    • 將大文件分割成若干 小數據塊,每個塊大小不超過內存容量
    • 依次將每個塊讀入內存,用 內部排序算法(如:快速排序)排序,生成 有序的歸并段(臨時文件)
  • 示例
    • 若內存可容納 100MB 數據,原始文件 1GB,則分成 10 個 100MB 的塊
    • 分別排序后得到 10 個有序歸并段

2. 歸并階段:合并歸并段

  • 核心思想:利用 多路歸并算法(如:k 路歸并),每次從 k 個歸并段中讀取最小數據,合并成最終有序文件。
  • 關鍵點
    • 減少磁盤 I/O 次數:通過增加歸并路數 k(受內存限制),減少歸并輪次。
    • 緩沖區管理:在內存中為每個歸并段分配輸入緩沖區,以及輸出緩沖區,減少讀寫次數。

---------------實現---------------

四、文件歸并

文件二路歸并排序思路是什么?

文件數據排序與歸并流程:

1. 初始分塊排序

  • 從原始數據中每次讀取 n 個值,排序后分別寫入兩個臨時文件 file1file2

    • 例如:首次讀取前 n 個值排序后寫入 file1,再讀取接下來的 n 個值排序后寫入 file2

2. 首次歸并操作

  • 使用歸并排序的思想,同時讀取 file1file2 中的數據,逐段比較兩者的當前最小值
  • 將較小的值依次尾插到一個新文件 mfile 中,最終將 mfile 合并為一個有序文件

3. 文件清理與重命名

  • 刪除已歸并完成的 file1file2
  • mfile 重命名為 file1,作為下一輪歸并的基礎有序文件

4. 后續分塊與歸并循環

  • 再次從原始數據中讀取 n 個值,排序后寫入新的 file2(若原始數據已讀完,則跳過此步)
  • 重復步驟 2 的歸并過程
    • file1(前一輪的有序結果)與 file2(新排序的塊)合并到 mfile
    • 再刪除舊文件并將 mfile 重命名為 file1

5. 終止條件與結果

  • 持續上述循環,直到原始數據無法再讀出 n 個值
  • 最終:所有數據經多次歸并后形成的完整有序數據將存儲在 file1

在這里插入圖片描述

在這里插入圖片描述

文件二路歸并排序怎么實現?

頭文件:ExternalSort.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
//任務1:包含要使用的頭文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>//任務2:聲明實現文件歸并的外排序需要使用“輔助函數”
//1.文件數據生成
//2.比較函數:用于調用qsort函數
void CreateNData();
int complete(const void* a, const void* b);//任務3:聲明實現文件歸并的外排序需要使用“核心函數”//1.從原文件中讀取n個數據,將其排序后寫入到新文件中
//2.合并兩個已排序的文件到一個新的文件int ReadNDataSortToFile(FILE* fout, int n, const char* file1);
void MergeFile(const char* file1, const char* file2, const char* mfile);

實現文件:ExternalSort.c

#include "ExternalSort.h"/*------------------------------------------實現:“輔助的函數”------------------------------------------*/
//1.實現:“創建大量的文件數據”
void CreateNData()
{/*-----------------第一階段:準備隨機條件-----------------*///1.設置要生成隨機數的數量const int N = 10000000; //生成1千萬個隨機整數//2.初始化隨機數的種子 ----> 確保每次運行生成的隨機數序列都是不同的srand((unsigned int)time(NULL));/*-----------------第二階段:準備寫入的文件-----------------*///1.定義寫入的文件的文件的名稱const char* file = "data.txt";//2.以“寫入的模式”打開文件 (注:如果文件已經存在則將原文件清空,否則創建新的文件)FILE* fin = fopen(file, "w");//3.檢查文件是否打開成功if (fin == NULL){perror("fopen fail");return;}/*-----------------第三階段:生成隨機數并將其寫入到文件中-----------------*///1.使用for循環進行N次:“隨機數的生成 + 寫入到文件中”for (int i = 0; i < N; i++){//1.1:生成隨機數int x = rand() + i;//1.2:將隨機數寫入文件中fprintf(fin, "%d\n", x);  //注:這里寫入的時候將換行符也寫入到了文件中 ---> 方便我們使用fscanf進行從文件中讀取數字}//2.關閉文件fclose(fin);}/*** @brief 比較函數,用于qsort等排序算法的元素比較** @param a 指向第一個待比較元素的指針(void*通用指針類型)* @param b 指向第二個待比較元素的指針(void*通用指針類型)* @return int 返回比較結果:*             - 負數:a < b*             - 零:a == b*             - 正數:a > b** @note 1. 這是標準的qsort比較函數格式*       2. 使用指針解引用和類型轉換來獲取整數值*       3. 返回a-b實現升序排序,b-a可實現降序排序*       4. 注意整數溢出風險(對大數建議使用條件判斷替代減法)*/
//2.實現:“兩個數字的大小比較”的輔助函數 ---> 由于qsort函數的調用
int complete(const void* a, const void* b)
{// 1. 將void*指針轉換為int*指針//    - 這是必要的,因為qsort使用通用指針void*//    - 我們知道實際比較的是int類型數據const int* pa = (const void*)a;const int* pb = (const void*)b;//2.解引用指針獲取實際整數值int valA = *pa;int valB = *pb;// 3. 計算并返回比較結果//    - 返回valA-valB實現升序排序//    - 這種實現簡潔但可能有整數溢出風險//    - 替代方案(避免溢出)://      if(valA < valB) return -1;//      if(valA > valB) return 1;//      return 0;return (valA - valB);/*上面的三步驟可以合并為一步驟:return(*(const int*)a - *(const int*)b);  //升序排序*/
}/*------------------------------------------實現:“核心的函數”------------------------------------------*//*** @brief 從輸入文件中讀取最多n個整數數據,排序后寫入輸出文件** @param fout 輸入文件指針(已打開的可讀文件)* @param n 請求讀取的最大數據個數* @param file1 輸出文件名(排序后的數據將寫入此文件)* @return int 實際讀取并處理的數據個數,0表示無數據或出錯** @note 函數執行流程:*       1. 分配內存緩沖區*       2. 從文件讀取數據*       3. 對數據進行排序*       4. 將排序結果寫入新文件*       5. 清理資源并返回結果*///1.實現:“從原文件中讀取n個數據,將其排序后寫入到新文件中”
int ReadNDataSortToFile(FILE* fout, int n, const char* file)
{/*-------------------------------第一階段:在內存中開辟空間又來存儲從文件讀到的部分數據-------------------------------*///1.在內存中開辟數組空間用于存儲從文件中讀取的n個數據 (空間的大小:足夠存儲請求的最大的空間)int* a = (int*)malloc(n * sizeof(int));if (a == NULL){perror("malloc fail");return 0;}/*-------------------------------第二階段:從文件中讀取數據到內存的數組中-------------------------------*///1.定義一個臨時的變量用于存儲從文件中讀取的每一個數字int x;//2.定義一個變量用于:記錄從文件讀取到內存中的數據的數量int num = 0;//3.使用for循環從文件中讀取數據for (int i = 0; i < n; i++){//3.1:判斷是否讀到了文件的末尾if (fscanf(fout, "%d", &x) == EOF)   //EOF表示文件結束或讀取錯誤{ break;}//3.2:將讀取的數據存儲到內存的數組中a[num++] = x;}//4.檢查是否讀取到任何的數據if (num == 0){free(a);return 0;}/*-------------------------------第三階段:對讀取到內存中的數據進行排序-------------------------------*///使用標準庫的qsort函數qsort(a, num, sizeof(int), complete);  //參數:數組指針,元素個數,元素大小,比較函數/*-------------------------------第四階段:將排序好的數據寫入到新文件中-------------------------------*///1.以“只寫的模式”打開新文件file目的是為了寫入排序好的數據FILE* fin = fopen(file, "w");if (fin == NULL){//1.1:文件打開失敗,先釋放內存free(a);//1.2:輸出錯誤信息perror("fopen fail");//1.3:返回0表示失敗return 0;}//2.使用for循環將排序好的數據寫入到新文件file中for (int i = 0; i < num; i++){fprintf(fin, "%d\n", a[i]);}/*-------------------------------第五階段:釋放資源-------------------------------*///1.釋放動態開辟的內存free(a);//2.關閉新文件filefclose(fin);/*-------------------------------第六階段:返回實際處理的數據個數-------------------------------*/return num;
}/*** @brief 合并兩個已排序的整數文件到一個新文件(歸并操作)** @param file1 第一個已排序的輸入文件名* @param file2 第二個已排序的輸入文件名* @param mfile 合并后的輸出文件名** @note 該函數執行經典的兩路歸并操作,要求:*       1. 輸入文件必須已按升序排列*       2. 文件內容為每行一個整數*       3. 輸出文件將包含所有輸入數據并保持有序*/
//2.實現:“合并兩個已排序文件到一個新文件中”
void MergeFile(const char* file1, const char* file2, const char* mfile)
{/*-------------------------------第一階段:打開文件-------------------------------*///1.以“只讀模式”打開文件file1FILE* fout1 = fopen(file1, "r");if (fout1 == NULL){perror("fopen fail for file1");  //更明確的錯誤信息return;}//2.以“只讀模式”打開文件file2FILE* fout2 = fopen(file2, "r");if (fout2 == NULL){perror("fopen fail for file2");fclose(fout1);  //資源清理:關閉已經成功打開的第一個文件return;}//3.以“只寫模式”打開文件mfileFILE* fin = fopen(mfile, "w");if (fin == NULL){perror("fopen fail for mfile");fclose(file1);fclose(file2);return;}/*-------------------------------第二階段:文件歸并-------------------------------*///1.定義兩個變量存儲從兩個小文件中讀取的數據int x1, x2;//2.定義兩個變量存儲fscanf函數的返回值 --> 目的:判斷何時停止歸并int ret1, ret2;//3.先分別從兩個小文件中讀取一個數據到變量中ret1 = fscanf(fout1, "%d", &x1);ret2 = fscanf(fout2, "%d", &x2);//4.使用while循環進行雙路歸并 while (ret1 != EOF && ret2 != EOF) //當兩個小文件中有一個文件已經讀取結束時,歸并就結束了 ---> 反面就是while循環的條件{//4.1:當從文件file1中讀取的數據更小的話,則將x1添加到新文件mfile中if (x1 < x2){//1.寫入fprintf(fin, "%d\n", x1);//2.再讀ret1 = fscanf(fout1, "%d", &x1);}//4.2:當從文件file2中讀取的數據更小的話,則將x2添加到新文件mfile中else{//1.寫入fprintf(fin, "%d\n", x2);//2.再讀ret2 = fscanf(fout2, "%d", &x2);}}/*-------------------------------第三階段:處理某一個文件中的剩余數據-------------------------------*///情況1:小文件file1還有剩余數據(file2已耗盡)while (ret1 != EOF){//1.寫入fprintf(fin, "%d\n", x1);//2.再讀ret1 = fscanf(fout1, "%d", &x1);}//情況2:小文件file2還有剩余數據(file1已耗盡)while (ret2 != EOF){//1.寫入fprintf(fin, "%d\n", x2);//2.再讀ret2 = fscanf(fout2, "%d", &x2);}/*-------------------------------第三階段:資源清理-------------------------------*/fclose(fout1);fclose(fout2);fclose(fin);
}

主程序文件:Main.c

#include "ExternalSort.h"/*** @brief 主函數 - 實現外部排序的核心流程** @return int 程序退出狀態碼(0表示成功)** @note 該程序實現完整的外部排序過程:*       1. 生成測試數據*       2. 分割大文件為有序小文件*       3. 多輪歸并排序*       4. 最終生成完全有序的大文件*/int main()
{/*-------------------------------第一階段:數據準備-------------------------------*///1.生成包含隨機數的初始隨機文件"data.txt"//CreateNData();//2.定義臨時文件名const char* file1 = "file1.txt";  //主歸并文件(每輪歸并后保存中間結果)const char* file2 = "file2.txt";  //輔助歸并文件(存儲新讀取的數據塊)const char* mfile = "mfile.txt";  //歸并臨時文件(存儲每輪歸并結果)/*-------------------------------第二階段:文件初始化-------------------------------*///1.以“只讀模式”打開原始數據文件"data.txt"FILE* fout = fopen("data.txt", "r");if (fout == NULL){perror("fopen fail");return 1; //返回非零表示錯誤退出}/*-------------------------------第三階段:原始數據文件分割-------------------------------*///1.設置分割出的每個小文件的大小(根據內存容量調整)int M = 1000000;  //每次處理1百萬個整數//2.讀取并排序第一批數組到file1中ReadNDataSortToFile(fout, M, file1);//3.讀取并排序第一批數組到file2中ReadNDataSortToFile(fout, M, file2);/*-------------------------------第四階段:多輪歸并-------------------------------*///1.使用while死循環進行多輪歸并while (1) //我們并不清楚大文件中到底有多少的數據,即我們不清楚我們要歸并多少輪 ---->  所以:無限循環,通過內部break退出{/*----------第一步:歸并存儲在兩個小文件file1和file2中的已經排好序的數據到一個較大的文件mfile中----------*/MergeFile(file1, file2, mfile);/*----------第二步:清理兩個小文件file1和file2----------*/if (remove(file1) != 0) //安全刪除不再需要的中間文件perror("Warning: Failed to remove file1");if (remove(file2) != 0)perror("Warning: Failed to remove file2");/*----------第三步:將歸并出來的那個較大的文件mfile重命名為file1----------*/if (rename(mfile, file1) != 0) //安全重命名文件mfile {perror("Warning: Failed to rename mfile");break;}/*----------第四步:從原數據文件中讀取下一批數據到文件file2----------*///1.記int read_count = 0;//2.讀read_count = ReadNDataSortToFile(fout, M, file2);//3.檢if (read_count == 0){break; // 讀取不到數據,排序完成}/*1.歸并2.清理3.輪轉4.再讀*/// 調試用代碼塊(可取消注釋)if (read_count < M){printf("最后一塊有 %d 個元素\n", read_count);;}}/*-------------------------------第五階段:釋放資源 + 結束程序-------------------------------*///1.關閉原始數據文件fclose(fout);//2.程序成功結束return 0;
}

運行結果

文件歸并操作

在這里插入圖片描述

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/83095.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/83095.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/83095.shtml

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

相關文章

DDP與FSDP:分布式訓練技術全解析

DDP與FSDP:分布式訓練技術全解析 DDP(Distributed Data Parallel)和 FSDP(Fully Sharded Data Parallel)均為用于深度學習模型訓練的分布式訓練技術,二者借助多 GPU 或多節點來提升訓練速度。 1. DDP(Distributed Data Parallel) 實現原理 數據并行:把相同的模型復…

MATLAB實戰:實現數字調制解調仿真

以下是使用MATLAB實現BPSK和QPSK數字調制解調仿真的完整代碼。該代碼包括調制、AWGN信道、匹配濾波/相關解調、星座圖繪制以及誤碼率計算與理論值比較。 %% 清理環境 clear all; close all; clc; %% 參數設置 numBits 100000; % 傳輸比特數 EbN0_dB 0:2:10; …

數據可視化的定義和類型

數據可視化是一種將數據轉換為圖形或視覺表示的方法。想象一下&#xff0c;你面前有一堆數字和表格&#xff0c;看著這些&#xff0c;可能會讓人頭大。數據可視化就像是給這些枯燥的數字畫上一幅畫。它用圖表、地圖和各種有趣的圖形&#xff0c;幫我們把難懂的數字變得容易看懂…

*JavaScript中的Symbol類型:唯一標識符的藝術

JavaScript中的Symbol類型&#xff1a;唯一標識符的藝術 在JavaScript的世界中&#xff0c;數據類型一直是開發者關注的焦點。從基本的Number、String到后來的Symbol&#xff0c;每一種類型的引入都為語言本身注入了新的活力。而今天我們要聊的主角——Symbol&#xff0c;是ES…

粽葉飄香時 山水有相逢

粽葉飄香時 山水有相逢 尊敬的廣大客戶們&#xff1a; 五月初五&#xff0c;艾葉幽香。值此端午佳節&#xff0c;衡益科技全體同仁向您致以最誠摯的祝福&#xff01; 這一年我們如同協同競渡的龍舟&#xff0c;在數字化轉型的浪潮中默契配合。每一次技術對接、每輪方案優化&a…

一文認識并學會c++模板初階

文章目錄 泛型編程&#xff1a;概念 函數模板概念&#xff1a;&#x1f6a9;函數模板格式原理&#xff1a;&#x1f6a9;函數模板實例化與非模板函數共存 類模板類模板實例化 泛型編程&#xff1a; 概念 &#x1f6a9;編寫與類型無關的通用代碼&#xff0c;是代碼復寫一種手段…

Python實現VTK-自學筆記(5):在三維世界里自由舞蹈——高級交互與動態可視化

深夜的臺燈在屏幕上投下溫暖的弧光,指尖敲擊鍵盤的節奏逐漸與窗外雨滴聲融為一體。這是我在VTK世界的第五次探險,此刻顯示器里旋轉的彩色分子模型仿佛在對我眨眼——它渴望被觸摸、被塑造、被賦予生命。今天,就讓我們用Python為這些沉默的數據注入靈魂,見證靜態可視化如何蛻…

智慧充電樁數字化管理平臺:環境監測與動態數據可視化技術有哪些作用?

隨著新能源汽車的普及&#xff0c;智慧充電樁作為基礎設施的重要組成部分&#xff0c;正逐步向數字化、智能化方向發展。環境監測與動態數據可視化技術的應用&#xff0c;為充電樁的高效管理和運維提供了全新解決方案。通過實時采集環境參數與運行數據&#xff0c;并結合可視化…

LVS +Keepalived高可用群集

目錄 一&#xff1a;Keepalived雙機熱備基礎知識 1.Keepalived 概述及安裝 1.1.Keepalived的熱備方式 1.2.Keepalived 的安裝與服務控制 &#xff08;1&#xff09;安裝Keepalived &#xff08;2&#xff09;控制Keepalived服務 2.使用Keepalived實現雙機熱備 2.1.主服務…

深入剖析Java類加載機制:雙親委派模型的突破與實戰應用

引言&#xff1a;一個詭異的NoClassDefFoundError 某金融系統在遷移到微服務架構后&#xff0c;突然出現了一個詭異問題&#xff1a;在調用核心交易模塊時&#xff0c;頻繁拋出NoClassDefFoundError&#xff0c;但類明明存在于classpath中。經過排查&#xff0c;發現是由于不同…

Go語言的context

Golang context 實現原理 本篇文章是基于小徐先生的文章的修改和個人注解&#xff0c;要查看原文可以點擊上述的鏈接查看 目前我這篇文章的go語言版本是1.24.1 context上下文 context被當作第一個參數&#xff08;官方建議&#xff09;&#xff0c;并且不斷的傳遞下去&…

BERT、GPT-3與超越:NLP模型演進全解析

自然語言處理&#xff08;NLP&#xff09;領域近年來經歷了前所未有的變革&#xff0c;從早期的統計方法到如今的深度學習大模型&#xff0c;技術的進步推動了機器理解、生成和交互能力的飛躍。其中&#xff0c;BERT和GPT-3作為兩個里程碑式的模型&#xff0c;分別代表了不同的…

Kanass入門教程- 事項管理

kanass是一款國產開源免費、簡潔易用的項目管理工具&#xff0c;包含項目管理、項目集管理、事項管理、版本管理、迭代管理、計劃管理等相關模塊。工具功能完善&#xff0c;用戶界面友好&#xff0c;操作流暢。本文主要介紹事項管理使用指南。 1、添加事項 事項有多種類型 分…

2025年5月個人工作生活總結

本文為 2025年5月工作生活總結。 研發編碼 一個項目的臨時記錄 月初和另一項目同事向業主匯報方案&#xff0c;兩個項目都不滿意&#xff0c;后來領導做了調整&#xff0c;將項目合并&#xff0c;拆分了好幾大塊。原來我做的一些工作&#xff0c;如數據庫、中間件等&#xff…

? Unity AVProVideo插件自帶播放器 腳本重構 實現視頻激活重置功能

一、功能概述 本筆記記錄直接修改插件自帶的場景播放其中 原始的 MediaPlayerUI 腳本,實現激活時自動重置播放器的功能。 我用的插件版本是 AVPro Video - Ultra Edition 2.7.3 修改后的腳本將具備以下特性: 激活 GameObject 時自動重置播放位置到開頭 可配置是否在重置后自…

5.31 數學復習筆記 22

前面的筆記&#xff0c;全部寫成一段&#xff0c;有點難以閱讀。現在改進一下排版。另外&#xff0c;寫筆記實際上就是圖一個放松呢&#xff0c;關鍵還是在于練習。 目前的計劃是&#xff0c;把講義上面的高數例題搞清楚之后&#xff0c;大量刷練習冊上面的題。感覺不做幾本練…

什么是 WPF 技術?什么是 WPF 樣式?下載、安裝、配置、基本語法簡介教程

什么是 WPF 技術&#xff1f;什么是 WPF 樣式&#xff1f;下載、安裝、配置、基本語法簡介教程 摘要 WPF教程、WPF開發、.NET 8 WPF、Visual Studio 2022 WPF、WPF下載、WPF安裝、WPF配置、WPF樣式、WPF樣式詳解、XAML語法、XAML基礎、MVVM架構、數據綁定、依賴屬性、資源字典…

ROS2與Unitree機器人集成指南

Tested systems and ROS2 distro systemsROS2 distroUbuntu 20.04foxyUbuntu 22.04humblesrc目錄上級才可以colcon build git clone https://github.com/unitreerobotics/unitree_ros2 Install Unitree ROS2 package 1. Dependencies sudo apt install ros-humble-rmw-cyclon…

深入探討集合與數組轉換方法

目錄 1、Arrays.asList() 1.1、方法作用 1.2、內部實現 1.3、修改元素的影響 1.4、注意事項 2、list.toArray() 2.1、方法作用 2.2、內部實現 2.3、修改元素的影響 2.4、特殊情況 1、對象引用 2、數組copy 3、對比總結 4、常見誤區與解決方案 5、實際應用建議…

深入理解交叉熵損失函數——全面推演各種形式

帶你從不一樣的視角綜合認識交叉熵損失&#xff0c;閱讀這篇文章&#xff0c;幫你建立其分類問題&#xff0c;對比學習&#xff0c;行人重識別&#xff0c;人臉識別等問題的聯系&#xff0c;閱讀這篇文章相信對你閱讀各種底層深度學習論文有幫助。 引言 1. 重新理解全連接層&…