6.二叉樹.題目3

6.二叉樹.題目3

  • 題目
    • 17.二叉搜索樹中的眾數
    • 18.二叉樹的最近公共祖先
    • 19.二叉樹搜索樹的最近公共祖先
    • 20.二叉搜索樹中的插入操作。
      • 普通二叉樹的刪除方式
    • 21.刪除二叉搜索樹中的節點
    • 22.修剪二叉樹
    • 23.將有序數組轉化為二叉搜索樹
    • 24.把二叉搜索樹轉化為累加樹
  • 總結

題目

17.二叉搜索樹中的眾數

(題目鏈接)
給定一個有相同值的二叉搜索樹(BST),找出 BST 中的所有眾數(出現頻率最高的元素。
首先如果不是二叉搜索樹的話,應該怎么解題,是二叉搜索樹,又應該如何解題,兩種方式做一個比較,可以加深大家對二叉樹的理解。

  • 如果不是二叉搜索樹:最直觀的辦法是先將樹遍歷一遍,再使用map統計頻率,然后把頻率排序,最后取高頻的元素的集合
/* 表示在排序時,a應該排在b前面。因此,當我們使用這個函數對vector<pair<int, int>>進行排序時,頻率最高的元素會被放在前面*/
bool static cmp (const pair<int, int>& a, const pair<int, int>& b) {return a.second > b.second;
}vector<int> findMode(TreeNode* root) {unordered_map<int, int> map; // key:元素,value:出現頻率vector<int> result;if (root == NULL) return result;// 遍歷樹,并將樹出現頻率統計在map中searchBST(root, map);vector<pair<int, int>> vec(map.begin(), map.end());sort(vec.begin(), vec.end(), cmp); // 給頻率排個序result.push_back(vec[0].first);for (int i = 1; i < vec.size(); i++) {// 取最高的放到result數組中if (vec[i].second == vec[0].second) result.push_back(vec[i].first);else break;}return result;}
  • 如果是二叉搜索樹:將二叉搜索樹通過中序遍歷展開為遞增序列,然后通過一次遍歷即可把眾數放入數組res中。使用了pre指針和cur指針的技巧。使用一個指針指向前一個節點,這樣每次cur(當前節點)才能和pre(前一個節點)作比較。
private:int maxcount = 0;int count = 0;TreeNode* pre = nullptr;std::vector<int> res;void backtracking(TreeNode* root){if(root==nullptr) return;backtracking(root->left);// 根據pre,root修改計數countif(pre==nullptr) count=1;else if(pre->val==root->val) count++;else count=1; pre = root; // 更新pre的指針位置if(count==maxcount) res.push_back(root->val);if(count>maxcount){res.clear();maxcount = count;res.push_back(root->val);}backtracking(root->right);return;}
public:vector<int> findMode(TreeNode* root) {res.clear();backtracking(root);return res;}

18.二叉樹的最近公共祖先

(題目鏈接)
給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。最近公共祖先的定義:對于有根樹 T 的兩個結點 p、q,最近公共祖先表示為一個結點 x,滿足 x 是 p、q 的祖先且 x 的深度盡可能大(一個節點也可以是它自己的祖先)。說明:所有節點的值都是唯一的;p、q 為不同節點且均存在于給定的二叉樹中。
尋找最近公共祖先節點,需要我們從二叉樹的底部往頂部進行處理,這就需要使用后序遍歷的方法(左右上)
終止條件:當cur==nullptr,以及當cur==p || q說明也遍歷到了目標節點,到達葉子節點位置時結束
確定單層遞歸邏輯-本題的遞歸函數有返回值,因為回溯的過程需要遞歸函數的返回值做判斷,而遞歸函數有返回值就是要遍歷某一條邊,但有返回值也要看如何處理返回值。

// 搜索一條邊
if (遞歸函數(root->left)) return ;
if (遞歸函數(root->right)) return ;
// 搜索整個樹
left = 遞歸函數(root->left);  // 左
right = 遞歸函數(root->right); // 右
left與right的邏輯處理;         // 中 

在遞歸函數有返回值的情況下:如果要搜索一條邊,遞歸函數返回值不為空的時候,立刻返回;如果搜索整個樹,直接用一個變量left、right接住返回值,這個left、right后序還有邏輯處理的需要,也就是后序遍歷中處理中間節點的邏輯(也是回溯)
在這里插入圖片描述

    TreeNode* backtracking(TreeNode* root, TreeNode* p, TreeNode* q){// 終止條件if(root==nullptr) return root;if(root==p || root==q) return root;TreeNode* left = backtracking(root->left, p, q);TreeNode* right = backtracking(root->right, p, q);// 后序遍歷,中序需要左,右子樹的值進行判斷if(left!=nullptr && right!=nullptr) return root;else if(left==nullptr && right!=nullptr) return right;else if(left!=nullptr && right==nullptr) return left;else return nullptr;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {return backtracking(root, p, q);}

19.二叉樹搜索樹的最近公共祖先

(題目鏈接)
因為是有序樹,所以 如果 中間節點是 q 和 p 的公共祖先,那么 中節點的數組 一定是在 [p, q]區間的。那么只要從上到下去遍歷,遇到 cur節點是數值在[p, q]區間中則一定可以說明該節點cur就是p 和 q的公共祖先,那么該如何判斷是最近祖先?
在這里插入圖片描述
跟據以上的例子,所以當我們從上向下去遞歸遍歷,第一次遇到 cur節點是數值在[q, p]區間中,那么cur就是 q和p的最近公共祖先。

    TreeNode* backtracking(TreeNode* root, TreeNode* p, TreeNode* q){if(root==nullptr) return root;if(root->val>p->val && root->val>q->val){TreeNode* left = backtracking(root->left, p, q);if(left!=nullptr) return left;}if(root->val<p->val && root->val<q->val){TreeNode* right = backtracking(root->right, p, q);if(right!=nullptr) return right;}return root;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {return backtracking(root, p, q);}

20.二叉搜索樹中的插入操作。

(題目鏈接)
給定二叉搜索樹(BST)的根節點和要插入樹中的值,將值插入二叉搜索樹。 返回插入后二叉搜索樹的根節點。 輸入數據保證:新值和原始二叉搜索樹中的任意節點值都不同。其實只要遍歷二叉搜索樹,找到空節點 插入元素就可以了,那么這道題其實就簡單了。
遞歸函數設置返回值,可以利用返回值完成新加入的節點與其父節點的賦值操作
終止條件:當cur==nullptr,到達葉子節點位置時結束,就是要插入新節點的位置,并把插入的節點返回。
單層遞歸的邏輯:二叉搜索樹的遞歸方向,根據val值與root->val的比值大小

	// 遞歸函數設置返回值,用于終止條件時新節點的賦值TreeNode* insertIntoBST(TreeNode* root, int val) {if(root==nullptr){TreeNode* node = new TreeNode(val);return node;}if(val>root->val) root->right = insertIntoBST(root->right, val); //在終止條件時完成對root的插入新子節點if(val<root->val) root->left = insertIntoBST(root->left, val);return root;}

當然該遞歸函數也可不設置返回值,需要記錄每次遞歸前上一個節點(parent),遇到空節點了,就讓parent左孩子或者右孩子指向新插入的節點。然后結束遞歸。

	// 遞歸函數不設置返回值,需要外部指針記錄父節點TreeNode* par;void backtracking(TreeNode* root, int val){if(root==nullptr){TreeNode* node = new TreeNode(val);if(val>par->val) par->right = node;else par->left = node;return;}par = root; //不需要回溯,只需記錄每次遞歸的父節點if(val>root->val) backtracking(root->right, val);if(val<root->val) backtracking(root->left, val);return;}TreeNode* insertIntoBST(TreeNode* root, int val) {par = new TreeNode(val);if(root==nullptr){root = new TreeNode(val);}backtracking(root, val);return root;}	

普通二叉樹的刪除方式

對于沒有數值大小排序需要的普通二叉樹,通用的二叉樹的刪除方法。主要分為兩個步驟

  1. 和目標節點的右子樹最左面節點交換
  2. 直接用nullptr覆蓋
	// 比較繞,需要思考以西。TreeNode* deleteNode(TreeNode* root, int key) {if (root == nullptr) return root;if (root->val == key) {if (root->right == nullptr) { // 這里第二次操作目標值:最終刪除的作用return root->left;}TreeNode *cur = root->right;while (cur->left) {cur = cur->left;}swap(root->val, cur->val); // 這里第一次操作目標值:交換目標值其右子樹最左面節點。}root->left = deleteNode(root->left, key);root->right = deleteNode(root->right, key);return root;}

21.刪除二叉搜索樹中的節點

(題目鏈接)
給定一個二叉搜索樹的根節點 root 和一個值 key,刪除二叉搜索樹中的 key 對應的節點,并保證二叉搜索樹的性質不變。刪除節點分為兩個步驟:1.找到要刪除的節點 2.刪除元素。但搜索二叉樹的刪除節點要比普通的二叉樹復雜多,因此涉及要刪除節點的子樹的重新排序的問題
遞歸函數參數,返回值:
終止條件:當cur==nullptr,到達葉子節點位置時結束
每層遞歸邏輯:得分情況處理(處理是在父節點parent層處理的)

  • 根據key,沒有找到要刪除的節點,不用處理,遍歷到空節點就返回了
  • 左右子節點都為空,則直接刪除該節點
  • 左節點為空,右節點非空,刪除該節點,右節點補位
  • 右節點為空,左節點非空,刪除該節點,左節點補位
  • 左右節點為非空,則將刪除節點的左子樹頭結點(左孩子)放到刪除節點的右子樹的最左面節點的左孩子上,返回刪除節點右孩子為新的根節點。(這樣操作的目的是二叉搜索樹的右子樹的元素是均大于左子樹的元素的,而右子樹的的最小值必在最深的左葉子節點處,因此若刪除父節點,則可以很自然地把左子樹的頭節點接到右子樹的最深左葉子節點的left端)

在這里插入圖片描述

    TreeNode* deleteNode(TreeNode* root, int key) {if(root==nullptr) return root;// 處理節點 因為遞歸函數有返回值-實現父節點修改處理if(root->val == key){if(root->left==nullptr && root->right==nullptr){delete root;return nullptr;}else if(root->left==nullptr && root->right!=nullptr){auto node = root->right;delete root;return node;}else if(root->right==nullptr && root->left!=nullptr){auto node = root->left;delete root;return node;}else{auto node = root->right;while(node->left!=nullptr) node=node->left;node->left = root->left;TreeNode* tmp = root;root = root->right;delete tmp; //釋放原本root的內存return root;}}//指定遞歸的方向if(root->val>key) root->left = deleteNode(root->left, key);if(root->val<key) root->right = deleteNode(root->right, key);return root;}

22.修剪二叉樹

(題目鏈接)
給定一個二叉搜索樹,同時給定最小邊界L 和最大邊界 R。通過修剪二叉搜索樹,使得所有節點的值在[L, R]中 (R>=L)。可能需要改變樹的根節點,所以結果應當返回修剪好的二叉搜索樹的新的根節點。
遞歸函數確定參數,返回值:有返回值,更方便,可以通過遞歸函數的返回值來移除節點(返回值是為了這一點服務的);
終止條件:當root==nullptr
單層遞歸的邏輯:1. (本層)如果root(當前節點)的元素小于low的數值,那么應該遞歸右子樹,并返回右子樹符合條件的頭結點;如果root(當前節點)的元素大于high的,那么應該遞歸左子樹,并返回左子樹符合條件的頭結點。2.(下一層)接下來要將下一層處理完左子樹的結果賦給root->left,處理完右子樹的結果賦給root->right

    TreeNode* trimBST(TreeNode* root, int low, int high) {if(root==nullptr) return nullptr;// 處理節點,相當于局部調整root節點附近if(root->val<low){TreeNode* right = trimBST(root->right, low, high);return right;}if(root->val>high){TreeNode* left = trimBST(root->left, low, high);return left;}root->left = trimBST(root->left, low, high);root->right = trimBST(root->right, low, high);return root;}

23.將有序數組轉化為二叉搜索樹

(題目鏈接)
將一個按照升序排列的有序數組,轉換為一棵高度平衡二叉搜索樹。高度平衡二叉樹指:一個高度平衡二叉樹是指一個二叉樹每個節點的左右兩個子樹的高度差的絕對值不超過 1
在這里插入圖片描述
做這道題目需要了解:1.從中序后序遍歷序列構造二叉樹,最大二叉樹,二叉搜索樹中的插入操作;刪除二叉搜索數中的節點。其實數組構造二叉樹,構成平衡樹是自然而然的事情,因為大家默認都是從數組中間位置取值作為節點元素,一般不會隨機取。
本質就是尋找分割點,分割點作為當前節點,然后遞歸左區間和右區間。但數組長度為偶數,中間節點有兩個,取不同的作為根節點,會造成不同的平衡二叉搜索樹。
在這里插入圖片描述
遞歸函數參數和返回值:首先是傳入數組,然后就是左下標left和右下標right;在構造二叉樹的時候盡量不要重新定義左右區間數組,而是用下標來操作原數組,此處定義使用的是左閉右閉區間
遞歸終止條件:當區間left > right的時候,就是空節點了
確定單層遞歸邏輯:所以可以這么寫:int mid = left + ((right - left) / 2);出于考慮right+left可能會出現越界的問題。取了中間位置,就開始以中間位置的元素構造節點,然后接著劃分區間,root的左孩子接住下一層左區間的構造節點,右孩子接住下一層右區間構造的節點。最后返回root
遞歸法

    TreeNode* traversal(std::vector<int>& nums, int left, int right){// 切割問題,根據區間下標返回if(left>right) return nullptr;int mid = left + (right-left)/2;TreeNode* root = new TreeNode(nums[mid]);root->left = traversal(nums, left, mid-1);root->right = traversal(nums, mid+1, right);return root; }TreeNode* sortedArrayToBST(vector<int>& nums) {return traversal(nums, 0, nums.size()-1);}

不斷中間分割,然后遞歸處理左區間,右區間,也可以說是分治;這需要應該對通過遞歸函數的返回值來增刪二叉樹很熟悉了,這也是常規操作。


24.把二叉搜索樹轉化為累加樹

(題目鏈接)
給出二叉搜索樹的根節點,該樹的節點值各不相同,請你將其轉換為累加樹(Greater Sum Tree)使每個節點 node 的新值等于原樹中大于或等于 node.val 的值之和。提示:樹中的節點數介于 0 和 104 之間;每個節點的值介于 -104 和 104 之間;樹中的所有值 互不相同;給定的樹為二叉搜索樹。
在這里插入圖片描述
從樹中可以看出累加的順序是右中左,所以我們需要反中序遍歷這個二叉樹,然后順序累加就可以了。本題依然需要一個pre指針記錄當前遍歷節點cur的前一個節點,這樣才方便做累加——采用pre指針的題目還有1.搜索樹的最小絕對值差,2.我的眾數
遞歸函數參數和返回值:不需要返回值,只需要使用pre記錄前一個節點的val作累加
終止條件:當cur==nullptr即可終止
單層遞歸的邏輯:遵循右中左遍歷順序,中間節點的操作是賦值為當前值+pre的值,并且更新pre值
遞歸法

    int pre=0;void traversal(TreeNode* root){if(root==nullptr) return;traversal(root->right);root->val += pre;pre = root->val;traversal(root->left);}TreeNode* convertBST(TreeNode* root) {pre = 0;traversal(root);return root;}

迭代法-深度優先


總結

求最小公共祖先:

  1. 需要從底向上遍歷,那么二叉樹,只能通過后序遍歷(即:回溯)實現從底向上的遍歷方式。
  2. 在回溯的過程中,必然要遍歷整棵二叉樹,即使已經找到結果了,依然要把其他節點遍歷完,因為要使用遞歸函數的返回值(也就是代碼中的left和right)做邏輯判斷
  3. 要理解如果返回值left為空,right不為空為什么要返回right,為什么可以用返回right傳給上一層結果

添加,刪除二叉樹節點:

  1. 二叉搜索樹刪除節點比增加節點復雜的多,二叉搜索樹添加節點只需要在葉子上添加就可以的,不涉及到結構的調整,而刪除節點操作涉及到結構的調整。
  2. 刪除節點,最關鍵的部分是處理該節點左右節點都存在的情況。

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

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

相關文章

LLM大模型本地部署與預訓練微調

以通義千問-1_8B-Chat為例&#xff0c;按照官方教程&#xff0c;簡單介紹如何將模型進行本地CPU部署以及預訓練微調&#xff1a; 1、環境條件&#xff1a;Linux 24G內存左右 2、本地部署&#xff1a; 提前安裝好git跟git lfs&#xff0c;否則可能拉取不到模型文件&#xff0c;g…

SQL面試題練習 —— 求連續段的起始位置和結束位置

目錄 1 題目2 建表語句3 題解 題目來源&#xff1a;拼多多。 1 題目 有一張表t_id記錄了id&#xff0c;id不重復&#xff0c;但是會存在間斷&#xff0c;求出連續段的起始位置和結束位置。 樣例數據 ----- | id | ----- | 1 | | 2 | | 3 | | 5 | | 6 | | 8 | | …

【教程】DPW 325T FPGA板卡程序下載與固化全攻略

到底什么是固化&#xff1f;&#xff1f;&#xff1f; 在開發板領域&#xff0c;"固化"通常指的是將軟件或操作系統的鏡像文件燒錄&#xff08;Flash&#xff09;到開發板的存儲介質上&#xff0c;使其成為開發板啟動時加載的系統。這個過程可以確保開發板在啟動時能…

從單點到全景:視頻匯聚/安防監控EasyCVR全景視頻監控技術的演進之路

在當今日新月異的科技浪潮中&#xff0c;安防監控領域的技術發展日新月異&#xff0c;全景攝像機便是這一領域的杰出代表。它以其獨特的360度無死角監控能力&#xff0c;為各行各業提供了前所未有的安全保障&#xff0c;成為現代安防體系中的重要組成部分。 一、全景攝像機的技…

【SpringMVC】第1-7章

第1章 初始SpringMVC 1.1 學習本套教程前的知識儲備 JavaSEHTMLCSSJavaScriptVueAJAX axiosThymeleafServletMavenSpring 1.2 什么是MVC MVC架構模式相關課程&#xff0c;在老杜的JavaWeb課程中已經詳細的講解了&#xff0c;如果沒有學過的&#xff0c;可以看這個視頻&…

抖音微短劇小程序平臺:源碼搭建與廣告回傳技術詳解

抖音微短劇小程序平臺&#xff1a;源碼搭建與廣告回傳技術詳解 在數字化時代&#xff0c;短視頻已成為大眾娛樂生活的重要組成部分。抖音微短劇小程序平臺&#xff0c;作為這一趨勢的佼佼者&#xff0c;不僅為用戶提供了豐富多樣的短視頻內容&#xff0c;還為創作者和廣告主提…

當下為什么越來越多的企業選擇產業園區,而不是寫字樓?

隨著經濟形勢的變化和各行業的升級轉型&#xff0c;我們發現越來越多的企業選擇扎根產業園而非傳統的寫字樓&#xff0c;這一現象背后真正的原因是什么呢&#xff1f;今天我們就站在企業自身發展的角度&#xff0c;全維度對比一下產業園與傳統寫字樓的區別&#xff0c;看是否能…

參加六西格瑪綠帶培訓是投資未來,還是花冤枉錢?

是否值得花費資金參加六西格瑪綠帶培訓&#xff0c;取決于多個因素。 從積極的方面來看&#xff0c;參加六西格瑪綠帶培訓具有以下潛在價值&#xff1a; 1. 提升專業技能&#xff1a;使您掌握一套系統的問題解決方法和流程改進工具&#xff0c;有助于在工作中更高效地解決復雜…

代碼隨想錄算法訓練營:14/60

非科班學習算法day14 | LeetCode266:翻轉二叉樹 &#xff0c;Leetcode101: 對稱二叉樹&#xff0c;Leetcode100:相同的的樹 &#xff0c;LeetCode572:另一顆樹的子樹&#xff0c;LeetCode104&#xff1a;二叉樹的最大深度&#xff0c;LeetCode559&#xff1a;N叉樹的最大深度 目…

CesiumJS【Basic】- #017 精靈動畫的渲染

文章目錄 精靈動畫的渲染1 目標2 實現3 資源文件精靈動畫的渲染 1 目標 完成動畫精靈圖(Animated Sprite Sheet)的渲染 2 實現 import * as Cesium from "cesium";const viewer = new Cesium.

SDK 程序卡在 AXI DMA 配置 (XAxiDma_CfgInitialize)的解決方法

在進行 AXI DMA 配置 時候代碼一直卡在XAxiDma_CfgInitialize函數出不來&#xff0c;也沒有打印報錯。 /* Initialize the XAxiDma device.*/CfgPtr XAxiDma_LookupConfig(DeviceId);if (!CfgPtr) {xil_printf("No config found for %d\r\n", DeviceId);return XST_…

Ubuntu安裝指定內核版本教程

Ubuntu安裝內核 1.查看當前os已安裝的內核 $sudo dpkg --get-selections |grep linux-image linux-image-5.10.0-1013-oem install linux-image-5.11.0-27-generic install linux-image-5.11.0-41-generic install …

ResNet-50算法

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 一、理論知識儲備 1.CNN算法發展 AlexNet是2012年ImageNet競賽中&#xff0c;由Alex Krizhevsky和Ilya Sutskever提出&#xff0c;在2012年ImageNet競賽中&a…

頭歌——機器學習——支持向量機案例

第1關&#xff1a;基于支持向量機模型的應用案例 任務描述 本關任務&#xff1a;編寫一個基于支持向量機模型的應用案例。 相關知識 在本應用案例中&#xff0c;我們借助一個具體的實際問題&#xff0c;來完整地實現基于支持向量機模型的開發應用。在此訓練中&#xff0c;我…

運籌系列93:VRP精確算法

1. MTZ模型 MTZ是Miller-Tucker-Zemlin inequalities的縮寫。除了定義是否用到邊 x i j x_{ij} xij?外&#xff0c;還需要定義一個 u i u_i ui?用來表示此時車輛的當前載貨量。注意這里x變量需要定義為有向。 這里定義為pickup問題&#xff0c;代碼為&#xff1a; using Ju…

數據庫系統概論-第11章并發控制

允許多個用戶同時使用同一個數據庫的數據庫系統稱為多用戶數據庫系統。 事務可以一個一個地中行執行&#xff0c;即每個時刻只有一個事務運行&#xff0c;其他事務必須等到這個事務結束以后方能運行。 單處理機系統中&#xff0c;事務的并行執行實際上是這些并行事務的并行操…

windows下載jdk并安裝步驟(保姆級教程)

一、下載jdk 下載地址: https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 二、雙擊下載好的jdk 更改安裝目錄然后點擊下一步 然后會彈出jre的安裝&#xff0c;需要選擇路徑&#xff08;注意&#xff1a;這里的路徑必須跟前面的jdk在…

ocr數據不夠,怎么造數據

1.確定特定字體類型&#xff1b; 2.收集合適的圖片作為背景 3.在背景圖上填寫特定字體的字符內容 1&#xff09;字體無法確認時怎么辦&#xff1f; 方法一&#xff1a;可以將文本行裁剪出來去網站上確認&#xff0c;網站鏈接&#xff1a;字體識別-在線掃一掃圖片找字體-搜字…

將huggingface的大模型轉換為safetensor格式

很多huggingface的大語言模型都是pytorch的格式&#xff0c;但是mindie需要safetensor格式&#xff0c;另外mindieservice加載原始的baichuan2-13b的模型出錯&#xff0c;后來排查是bfloat16數據格式的問題&#xff0c;所以這次轉換要一次性轉為float16的格式。 上代碼&#x…

計算機網絡:如何隱藏真實的IP和MAC地址?

目錄 一、什么是MAC地址二、什么是IP地址三、如何隱藏真實的MAC地址四、如何隱藏真實的IP地址 一、什么是MAC地址 MAC地址&#xff0c;全稱為媒體訪問控制地址&#xff08;Media Access Control Address&#xff09;&#xff0c;是一種用于網絡通信的唯一標識符。它是由IEEE 8…