React19源碼系列之createRoot的執行流程是怎么的?

2024年12月5日,react發布了react19版本。后面一段時間都將學習它的源碼,并著手記錄。

react官網:react19新特性
https://react.dev/blog/2024/12/05/react-19

在用vite創建react項目的使用,main.tsx主文件都會有以下代碼。

//import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'const root = createRoot(document.getElementById('root')!);
console.log('root',root)
root.render(// <StrictMode><App />// </StrictMode>,
)

該代碼是整個項目的入口。

在這里插入圖片描述

接下來我們就看看 createRoot 是如何執行。

createRoot 函數

createRoot 函數的主要作用是創建一個 React 應用的根節點,并對其進行一系列初始化操作,最終返回一個 ReactDOMRoot 對象。

function createRoot(container: Element | Document | DocumentFragment,options?: CreateRootOptions,
): RootType {// 用于控制是否默認啟用并發更新const concurrentUpdatesByDefaultOverride = false;// 表示是否啟用嚴格模式等。let isStrictMode = false;//let identifierPrefix = '';let onUncaughtError = defaultOnUncaughtError;let onCaughtError = defaultOnCaughtError;let onRecoverableError = defaultOnRecoverableError;let transitionCallbacks = null;//省略 options處理代碼// 創建容器對象 FiberRootNode
// FiberRootNode 對象,它是 React 協調器的核心數據結構,代表了整個 React 應用的根節點。const root = createContainer(container,ConcurrentRoot,//ConcurrentRoot 表示使用并發模式進行渲染。null,isStrictMode,concurrentUpdatesByDefaultOverride,identifierPrefix,onUncaughtError,onCaughtError,onRecoverableError,transitionCallbacks,);//在dom container節點添加屬性標記// 調用 markContainerAsRoot 函數,在 DOM 容器節點上添加一些屬性標記,用于標識該節點是 React 應用的根節點。markContainerAsRoot(root.current, container);// 處理容器元素// 如果傳入的 container 是一個注釋節點,則將其父節點作為根容器元素;否則,直接使用 container 作為根容器元素。const rootContainerElement: Document | Element | DocumentFragment =container.nodeType === COMMENT_NODE //8 注釋節點? (container.parentNode: any): container;// 事件委托處理// 在div#root上綁定各種事件,包括捕獲和冒泡階段// 可以實現事件委托,提高事件處理的效率。listenToAllSupportedEvents(rootContainerElement);// 根據創建的 FiberRootNode 對象 root,創建并返回一個 ReactDOMRoot 對象。這個對象提供了 render 方法,用于將 React 組件渲染到根節點上。return new ReactDOMRoot(root);
}

createContainer 函數

調用 createFiberRoot 函數來創建一個 FiberRoot 對象并返回。

函數參數含義:
containerInfo:類型為 Container,通常是一個 DOM 容器元素(如 div),用于指定 React 應用要掛載到的實際 DOM 節點。
tag:類型為 RootTag,用于標記根節點的類型,比如 ConcurrentRoot 表示使用并發模式渲染。
hydrationCallbacks:類型為 null | SuspenseHydrationCallbacks,在服務端渲染時,用于處理水合(hydration)過程中的回調函數。
isStrictMode:布爾類型,用于指示是否開啟嚴格模式。嚴格模式會對組件進行額外的檢查,幫助開發者發現潛在問題。
concurrentUpdatesByDefaultOverride:這個參數目前已被忽略,未來可能會移除。
identifierPrefix:字符串類型,用于為 React 元素生成唯一標識符的前綴。
onUncaughtError:錯誤處理回調函數,當發生未捕獲的錯誤時會調用此函數。
onCaughtError:錯誤處理回調函數,當錯誤被捕獲時調用,會提供更多錯誤信息,包括錯誤邊界組件。
onRecoverableError:錯誤處理回調函數,當發生可恢復的錯誤時調用。
transitionCallbacks:類型為 null | TransitionTracingCallbacks,用于跟蹤過渡(transition)狀態的回調函數。

function createContainer(containerInfo: Container,// 實際的dom容器tag: RootTag,// 渲染類型 并發模式或者傳統模式hydrationCallbacks: null | SuspenseHydrationCallbacks,isStrictMode: boolean,concurrentUpdatesByDefaultOverride: null | boolean,identifierPrefix: string,onUncaughtError: (error: mixed,errorInfo: {+componentStack?: ?string},) => void,onCaughtError: (error: mixed,errorInfo: {+componentStack?: ?string,+errorBoundary?: ?React$Component<any, any>,},) => void,onRecoverableError: (error: mixed,errorInfo: {+componentStack?: ?string},) => void,transitionCallbacks: null | TransitionTracingCallbacks,
): OpaqueRoot {// 設置為 false 表示不進行水合操作。水合操作通常用于服務端渲染,將服務端渲染的 HTML 與客戶端的 React 應用進行連接。const hydrate = false;// 初始子元素,這里設置為 null,表示一開始沒有初始的子元素。const initialChildren = null;//創建 FiberRoot// createFiberRoot 函數創建 FiberRoot 對象,該函數會根據傳入的參數初始化 FiberRoot 的各種屬性,包括根節點的類型、掛載的 DOM 容器、錯誤處理回調等,最終返回一個代表整個 React 應用根節點的 FiberRoot 對象。return createFiberRoot(containerInfo,tag,// 模式 并發模式hydrate,initialChildren,hydrationCallbacks,isStrictMode,identifierPrefix,onUncaughtError,onCaughtError,onRecoverableError,transitionCallbacks,null,);
}

createFiberRoot 函數

createFiberRoot 函數是 React 中用于創建 FiberRoot 對象的核心函數,FiberRoot 是整個 React 應用的根節點,負責管理應用的渲染和更新流程。該函數會初始化根節點的各種屬性,創建對應的 Fiber 節點,并進行一些狀態和更新隊列的初始化操作。

函數參數含義:
containerInfo:通常是一個 DOM 容器元素,用于指定 React 應用要掛載到的實際 DOM 節點。
tag:標記根節點的類型,如 ConcurrentRoot 表示使用并發模式渲染。
hydrate:布爾值,指示是否進行水合操作(用于服務端渲染)。
initialChildren:初始的子元素列表。
hydrationCallbacks:在水合過程中使用的回調函數。
isStrictMode:布爾值,指示是否開啟嚴格模式。
identifierPrefix:用于為 React 元素生成唯一標識符的前綴。
onUncaughtError:未捕獲錯誤的處理回調函數。
onCaughtError:已捕獲錯誤的處理回調函數。
onRecoverableError:可恢復錯誤的處理回調函數。
transitionCallbacks:用于跟蹤過渡狀態的回調函數。
formState:表單狀態信息。

function createFiberRoot(containerInfo: Container,// 實際的dom容器tag: RootTag,// 渲染模式 并發模式或者傳統模式hydrate: boolean,initialChildren: ReactNodeList,hydrationCallbacks: null | SuspenseHydrationCallbacks,isStrictMode: boolean,// 示范嚴格模式identifierPrefix: string,// 前綴onUncaughtError: (error: mixed,errorInfo: {+componentStack?: ?string},) => void,onCaughtError: (error: mixed,errorInfo: {+componentStack?: ?string,+errorBoundary?: ?React$Component<any, any>,},) => void,onRecoverableError: (error: mixed,errorInfo: {+componentStack?: ?string},) => void,transitionCallbacks: null | TransitionTracingCallbacks,formState: ReactFormState<any, any> | null,
): FiberRoot {// 創建 FiberRootNode 實例// 創建一個 FiberRootNode 實例,該實例代表整個 React 應用的根節點,包含了與 DOM 容器、根節點類型、錯誤處理等相關的信息。const root: FiberRoot = (new FiberRootNode(containerInfo,tag,// 并發模式hydrate,identifierPrefix,onUncaughtError,onCaughtError,onRecoverableError,formState,): any);if (enableSuspenseCallback) {// 設置水合回調函數root.hydrationCallbacks = hydrationCallbacks;}if (enableTransitionTracing) {// 設置過渡跟蹤回調函數root.transitionCallbacks = transitionCallbacks;}// 創建 Fiber 節點,該節點代表根組件的 Fiber 節點。const uninitializedFiber = createHostRootFiber(tag, isStrictMode);//root.current 指向當前的 Fiber 節點,建立 FiberRoot 到 Fiber 節點的引用。root.current = uninitializedFiber;//uninitializedFiber.stateNode 指向 FiberRoot,建立 Fiber 節點到 FiberRoot 的引用。uninitializedFiber.stateNode = root;// 根據是否啟用緩存,初始化 Fiber 節點的狀態。狀態對象包含初始子元素、是否水合以及緩存信息。if (enableCache) {// 創建緩存對象const initialCache = createCache();// 保留緩存引用retainCache(initialCache);// 將緩存對象賦值給根節點的 pooledCache 屬性root.pooledCache = initialCache;// 再次保留緩存引用retainCache(initialCache);// 初始化根 Fiber 節點的狀態const initialState: RootState = {element: initialChildren,//存儲初始的子元素列表 initialChildren,這些子元素是 React 應用開始渲染時的初始內容。isDehydrated: hydrate,//一個布爾值,用于指示是否處于水合狀態,其值來源于 hydrate 參數。cache: initialCache,// 存儲前面創建的緩存對象 initialCache,這樣根 Fiber 節點就可以訪問這個緩存對象。};// 存儲前面創建的緩存對象 initialCache,這樣根 Fiber 節點就可以訪問這個緩存對象。// memoizedState 用于存儲 Fiber 節點的狀態,后續在渲染和更新過程中,React 會根據這個狀態來決定如何渲染組件。uninitializedFiber.memoizedState = initialState;} else {const initialState: RootState = {element: initialChildren,isDehydrated: hydrate,cache: (null: any), // not enabled yet};uninitializedFiber.memoizedState = initialState;}// 初始化更新隊列// 調用 initializeUpdateQueue 函數,為 Fiber 節點初始化更新隊列,用于管理后續的狀態更新操作。initializeUpdateQueue(uninitializedFiber);// 返回 FiberRoot 對象return root;
}

fiberRoot節點與 fiber節點的關系:
fiberRootcurrent屬性 是根節點的fiber對象的引用。

在這里插入圖片描述

createHostRootFiber 函數

創建一個根 Fiber 節點,該節點代表整個 React 應用的根。在創建過程中,會根據不同的tag模式(如傳統模式、并發模式)以及是否開啟嚴格模式和性能分析器等條件,來設置 Fiber 節點的 mode 屬性,最后調用 createFiber 函數完成 Fiber 節點的創建。

函數參數含義:

  • tag,類型為 RootTag,用于標記根節點的類型。tag 的值可能為傳統模式(值為 0)或并發模式(ConcurrentRoot,值為 1)。
  • isStrictMode,布爾類型,指示是否開啟嚴格模式。嚴格模式會對組件進行額外的檢查,幫助開發者發現潛在問題。
function createHostRootFiber(tag: RootTag,isStrictMode: boolean,
): Fiber {//設置 mode 屬性,用于存儲 Fiber 節點的模式。let mode;//disableLegacyMode常量為trueif (disableLegacyMode || tag === ConcurrentRoot) {mode = ConcurrentMode; // 并發模式// 是否嚴格模式(只有開發環境與藕可能為true)// if (isStrictMode === true) {//  mode |= StrictLegacyMode | StrictEffectsMode;// }} else {mode = NoMode;// NoMode默認為0 即傳統模式}// enableProfilerTimer表示啟用性能分析器,isDevToolsPresent表示開發者工具存在// if (enableProfilerTimer && isDevToolsPresent) {// 相當于  mode = mode | ProfileMode    例如 (1 |2) = 3//   mode |= ProfileMode;// }//創建根 Fiber 節點,HostRoot常量為3return createFiber(HostRoot, null, null, mode);
}

initializeUpdateQueue 函數

initializeUpdateQueue函數的功能是為一個 Fiber 節點初始化更新隊列。

UpdateQueue<State> 類型的對象 queue,這個對象包含了更新隊列的各種屬性:

  • baseState:初始狀態,賦值為 fiber.memoizedState,memoizedState 存儲了當前 Fiber 節點的最新狀態。
  • firstBaseUpdatelastBaseUpdate:分別指向更新隊列中第一個和最后一個基礎更新,初始值都為 null。基礎更新是指那些已經被處理過,但由于某些原因(如優先級問題)還沒有應用到 baseState 上的更新。
  • shared:是一個包含共享信息的對象,其中:
    • pending:指向待處理的更新鏈表的尾部,初始值為 null。
    • lanes:表示更新的優先級,初始值為 NoLanes,代表沒有任何優先級。
    • hiddenCallbacks:用于存儲隱藏的回調函數,初始值為 null。
  • callbacks:用于存儲更新完成后的回調函數,初始值為 null。
function initializeUpdateQueue<State>(fiber: Fiber): void {const queue: UpdateQueue<State> = {baseState: fiber.memoizedState,firstBaseUpdate: null,lastBaseUpdate: null,shared: {pending: null,lanes: NoLanes,hiddenCallbacks: null,},callbacks: null,};// 將創建好的更新隊列 queue 賦值給 fiber 節點的 updateQueue 屬性,這樣 Fiber 節點就有了自己的更新隊列,后續的狀態更新操作可以通過這個隊列來進行管理。fiber.updateQueue = queue;
}

ReactDOMRoot 構造函數

ReactDOMRoot 構造函數的主要作用是創建一個 ReactDOMRoot 實例,并將傳入的 FiberRoot 對象存儲在實例的 _internalRoot 屬性中。

function ReactDOMRoot(internalRoot: FiberRoot) {this._internalRoot = internalRoot;
}

ReactDOMRoot.prototype.render 函數

renderReactDOMRoot原型上的一個方法,主要作用是在根 DOM 節點上渲染一個 React 元素。

ReactDOMHydrationRoot.prototype.render = ReactDOMRoot.prototype.render =// $FlowFixMe[missing-this-annot]function (children: ReactNodeList): void {const root = this._internalRoot;if (root === null) {throw new Error('Cannot update an unmounted root.');}//執行更新updateContainer(children, root, null, null);};

ReactDOMRoot.prototype.unmount 函數

unmount 方法是ReactDOMRoot原型上的一個方法,其主要作用是卸載 React 應用的根節點,清理相關資源,將根節點從 DOM 中移除,釋放內存并確保應用不再占用相關資源。

ReactDOMHydrationRoot.prototype.unmount = ReactDOMRoot.prototype.unmount =// $FlowFixMe[missing-this-annot]function (): void {// 獲取內部根節點實例const root = this._internalRoot;// 存在if (root !== null) {// 清空根實例的引用this._internalRoot = null;// root.containerInfo 存儲了 React 應用渲染的 DOM 容器節點信息。通過 root.containerInfo 獲取根節點對應的 DOM 容器節點。const container = root.containerInfo;// 同步更新容器updateContainerSync(null, root, null, null);// 刷新同步工作flushSyncWork();// 取消容器的根節點標記unmarkContainerAsRoot(container);}};

全局變量

const randomKey = Math.random().toString(36).slice(2);//internalInstanceKey 用于在 DOM 元素上存儲 React Fiber 實例的相關信息。
const internalInstanceKey = '__reactFiber$' + randomKey;// internalPropsKey 用于存儲傳遞給組件的 props 信息。
const internalPropsKey = '__reactProps$' + randomKey;const internalContainerInstanceKey = '__reactContainer$' + randomKey;// internalEventHandlersKey 用于存儲事件處理函數的相關信息。
const internalEventHandlersKey = '__reactEvents$' + randomKey;
const internalEventHandlerListenersKey = '__reactListeners$' + randomKey;
const internalEventHandlesSetKey = '__reactHandles$' + randomKey;
const internalRootNodeResourcesKey = '__reactResources$' + randomKey;
const internalHoistableMarker = '__reactMarker$' + randomKey;

工具函數 markContainerAsRoot

markContainerAsRoot的作用是將一個 DOM 容器節點標記為 React 應用的根容器,并將對應的 Fiber 根節點與該容器節點關聯起來。在 React 的渲染過程中,需要將 Fiber 樹與實際的 DOM 節點進行關聯。

函數參數含義:

  • hostRoot, 根節點fiber
  • node, DOM 容器節點
function markContainerAsRoot(hostRoot: Fiber, node: Container): void {// $FlowFixMe[prop-missing]node[internalContainerInstanceKey] = hostRoot;// 變量internalContainerInstanceKey = '__reactContainer$' + randomKey;
}

在這里插入圖片描述

工具函數 markContainerAsRoot

function unmarkContainerAsRoot(node: Container): void {// $FlowFixMe[prop-missing]node[internalContainerInstanceKey] = null;
}

流程圖

在這里插入圖片描述

后續繼續看FiberRoot節點和Fiber節點的結構以及root.render中的updateContainer是如何執行的。

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

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

相關文章

設備管理VTY(Telnet、SSH)

實驗目的&#xff1a;物理機遠程VTY通過telnet協議登錄AR1,ssh協議登錄AR2和sw 注意配置Cloud1&#xff1a; 注意&#xff01;&#xff01;博主的物理機VMnet8--IP&#xff1a;192.168.160.1&#xff0c;所以AR1路由0/0/0端口才添加IP&#xff1a;192.168.160.3&#xff0c;每個…

使用VisualStdio制作上位機(一)

文章目錄 使用VisualStudio制作上位機(一)寫在前面第一部分:創建應用程序第二部分:GUI主界面設計使用VisualStudio制作上位機(一) Author:YAL 做了一些補充更新,2025-3-16 寫在前面 1.達到什么目的呢 本文主要講怎么通過Visual Studio 制作上位機,全文會以制作過程…

Anaconda conda常用命令:從入門到精通

1 創建虛擬環境 conda create -n env_name python3.8 2 創建虛擬環境的同時安裝必要的包 conda create -n env_name numpy matplotlib python3.8 3 查看有哪些虛擬環境 以下三條命令都可以。注意最后一個是”--”&#xff0c;而不是“-”. conda env list conda info -e c…

Linux 下 MySQL 8 搭建教程

一、下載 你可以從 MySQL 官方下載地址 下載所需的 MySQL 安裝包。 二、環境準備 1. 查看 MySQL 是否存在 使用以下命令查看系統中是否已經安裝了 MySQL&#xff1a; rpm -qa|grep -i mysql2. 清空 /etc/ 目錄下的 my.cnf 執行以下命令刪除 my.cnf 文件&#xff1a; [roo…

【Go】函數閉包、堆和棧的概念

閉包 閉包機制解析 在函數式編程中&#xff0c;閉包&#xff08;Closure&#xff09; 是一種特殊的函數結構&#xff0c;其核心特性是能夠捕獲并持有外部函數的上下文環境變量。這一機制打破了傳統函數中局部變量的生命周期規則&#xff1a; 常規局部變量 在函數被調用時創建…

【源碼分析】Nacos服務注冊源碼分析-客戶端

Nacos客戶端入口 首先在我們使用Nacos時&#xff0c;會在客戶端引入對應的依賴&#xff0c;例如需要Nacos的注冊中心功能需要引入 <!--nacos-discovery 注冊中心依賴--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-c…

Java中關于Optional的 orElse 操作,以及 orElse 與 orElseGet 的區別

文章目錄 1. 大概說明2. 詳細分析2.1 .orElse 操作2.2 .orElse 的作用&#xff1a;避免空指針異常2.3 為什么要用&#xff1f;2.4 orElseGet如何使用2.5 orElse和orElseGet的區別 1. 大概說明 這篇文章的目的是為了說明&#xff1a; orElse 如何使用orElseGet 如何使用兩者的…

數據結構-樹(詳解)

目錄 一、樹的基本概念二、樹的節點結構三、樹的基本操作&#xff08;一&#xff09;插入操作&#xff08;二&#xff09;刪除操作&#xff08;三&#xff09;查找操作&#xff08;四&#xff09;遍歷操作 四、樹的實現五、總結 一、樹的基本概念 樹是一種非線性數據結構&…

【eNSP實戰】配置端口映射(NAT Server)

拓圖 要求&#xff1a; 將AR1上的GE 0/0/1接口的地址從TCP協議的80端口映射到內網 Web服務器80端口 AR1接口配置 interface GigabitEthernet0/0/0ip address 192.168.0.1 255.255.255.0 # interface GigabitEthernet0/0/1ip address 11.0.1.1 255.255.255.0 # ip route-s…

RabbitMQ 基本原理詳解

1. 引言 在現代分布式系統中&#xff0c;消息隊列&#xff08;Message Queue&#xff09;是實現異步通信、解耦系統組件、提高系統可靠性和擴展性的重要工具。RabbitMQ 作為一款開源的消息中間件&#xff0c;因其高性能、易用性和豐富的功能&#xff0c;被廣泛應用于各種場景。…

算法——層序遍歷和中序遍歷構造二叉樹

晴問 #include <iostream> #include <vector> #include <queue> #include <unordered_map>using namespace std;struct TreeNode {int data;TreeNode *left;TreeNode *right;TreeNode(int data) : data(data), left(nullptr), right(nullptr) {} };//…

prometheus自定義監控(pushgateway和blackbox)和遠端存儲VictoriaMetrics

1 pushgateway采集 1.1 自定義采集鍵值 如果自定義采集需求時&#xff0c;就可以通過寫腳本 定時任務定期發送數據到 pushgateway 達到自定義監控 1.部署 pushgateway&#xff0c;以 10.0.0.42 節點為例 1.下載組件 wget https://github.com/prometheus/pushgateway/relea…

feign配置重試次數不生效

一、問題產生 自定義重試次數&#xff0c;實現如下 ConditionalOnProperty(prefix "feign.client", name "enable", havingValue "true") Configuration public class FeignConfig {Beanpublic FeignInterceptor feignInterceptor() {retur…

Dify使用部署與應用實踐

最近在研究AI Agent&#xff0c;發現大家都在用Dify&#xff0c;但Dify部署起來總是面臨各種問題&#xff0c;而且我在部署和應用測試過程中也都遇到了&#xff0c;因此記錄如下&#xff0c;供大家參考。Dify總體來說比較靈活&#xff0c;擴展性比較強&#xff0c;適合基于它做…

二叉樹的統一迭代法 標記法

我們以中序遍歷為例&#xff0c;在二叉樹&#xff1a;聽說遞歸能做的&#xff0c;棧也能做&#xff01; (opens new window)中提到說使用棧的話&#xff0c;無法同時解決訪問節點&#xff08;遍歷節點&#xff09;和處理節點&#xff08;將元素放進結果集&#xff09;不一致的情…

BaseActivity 和 BaseFragment 的現代化架構:ViewBinding 與 ViewModel 的深度整合

BaseActivity 和 BaseFragment 實現&#xff0c;集成了 View Binding&#xff0c;并增加了對 Lifecycle 和 ViewModel 的支持&#xff0c;同時進一步簡化了代碼結構&#xff0c;使其更易用、更靈活。 啟用 View Binding 確保在 build.gradle 中啟用了 View Binding&#xff1a…

從零開始學習機器人---如何高效學習機械原理

如何高效學習機械原理 1. 理解課程的核心概念2. 結合圖形和模型學習3. 掌握公式和計算方法4. 理論與實踐相結合5. 總結和復習6. 保持好奇心和探索精神 總結 機械原理是一門理論性和實踐性都很強的課程&#xff0c;涉及到機械系統的運動、動力傳遞、機構設計等內容。快速學習機械…

剖析sentinel的限流和熔斷

sentinel的限流和熔斷 前言源碼分析滑動窗口源碼限流源碼熔斷源碼 完結撒花&#xff0c;sentinel源碼還是挺簡單的&#xff0c;如有需要收藏的看官&#xff0c;順便也用發財的小手點點贊哈&#xff0c;如有錯漏&#xff0c;也歡迎各位在評論區評論&#xff01; 前言 平時發起一…

硬盤分區誤刪后的數據救贖

一、硬盤分區誤刪的概述 硬盤分區誤刪&#xff0c;是許多電腦用戶在使用過程中可能遭遇的棘手問題。分區&#xff0c;作為硬盤上存儲數據的邏輯單元&#xff0c;一旦被誤刪除&#xff0c;不僅會導致該分區內的所有數據瞬間消失&#xff0c;還可能影響到整個硬盤的存儲結構和數…

代碼隨想錄算法訓練營第三十五天(20250303) |01背包問題 二維,01背包問題 一維,416. 分割等和子集 -[補卡20250316]

01背包問題 二維 鏈接 遍歷物品沒有大小順序要求重點是模擬&#xff0c;推導出遞推公式 #include <iostream> #include <vector>int main(){int m, n;std::cin>>m>>n;std::vector<int> weight(m,0),value(m,0);for(int i{0}; i<m; i){std:…