數據結構——樹(2)

數據結構基礎(12)

文章目錄

  • 數據結構基礎(12)
      • 二叉樹的先序遍歷
      • 先序遍歷
      • 中序遍歷
      • 后序遍歷
      • 二叉樹的層序遍歷
      • 由遍歷序列構造二叉樹
        • 前序 + 中序遍歷序列
        • 后序 + 中序遍歷序列
        • 層序 + 中序遍歷序列
      • 二叉樹的中序遍歷(缺點):
      • 中序線索二叉樹
      • 中序線索化
      • 先序線索化
      • 后序線索化
      • 中序線索二叉樹找中序后繼
      • 中序線索二叉樹找中序前驅
      • 中序線索二叉樹找先序后繼
      • 先序線索二叉樹找先序前驅
      • 后序線索二叉樹找后序前驅

二叉樹的先序遍歷

  • 遍歷:按某種次序把所有結點都訪問一遍 – > 線性結構
  • 層次遍歷:基于樹的層次特性確定的次序規則
  • 二叉樹的先/中/后序遍歷:基于樹的遞歸特性確定的次序規則

二叉樹的遞歸特性

  1. 要么是個空二叉樹
  2. 要么就是由“根節點 + 左子樹 + 右子樹”組成的二叉樹

先序遍歷:根左右(NLR)-- > 又叫先根遍歷

中序遍歷:左根右(LNR)- > 又叫中根遍歷

后序遍歷:左右根(LRN)- > 又叫后根遍歷

基礎圖:

A
B
C

先序遍歷: ABC

中序遍歷:BAC

后序遍歷:BCA

在加深一點:

A
B
C
D
E
F
G

先序遍歷: A B D E C F G

中序遍歷; D B E A F C G

后序遍歷:D E B F G C A

對算數表達式的“分析樹”:

先序遍歷 — > 前綴表達式

中序遍歷 — > 中綴表達式(需要加界限符)

后序遍歷 — > 后綴表達式

先序遍歷

先序遍歷(PreOrder)的操作過程如下:

  1. 若二叉樹為空,則什么也不做;
  2. 若二叉樹非空:
    ①訪問根結點;
    ②先序遍歷左子樹
    ③先序遍歷右子樹

實現代碼:

typedef struct BiTNode{ElemType data;struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;//先序遍歷
void PreOrder(BiTree T){if(T!=NULL){visit(T);                //訪問根結點PreOrder(T->lchild);     //遞歸遍歷左子樹PreOrder(T->rchild);     //遞歸遍歷右子樹}
}

第一次被訪問的點

空間復雜度:O(h)

中序遍歷

中序遍歷(InOrder)的操作過程如下:

  1. 若二叉樹為空,則什么也不做;
  2. 若二叉樹非空:
    ①先序遍歷左子樹;
    ②訪問根結點;
    ③先序遍歷右子樹。

實現代碼:

typedef struct BiTNode{ElemType data;struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;//中序遍歷
void InOrder(BiTree T){if(T!=NULL){InOrder(T->lchild);  //遞歸遍歷左子樹visit(T);            //訪問根結點InOrder(T->rchild);  //遞歸遍歷右子樹}
}

第二次被訪問的點

后序遍歷

后序遍歷(PostOrder)的操作過程如下:

  1. 若二叉樹為空,則什么也不做;
  2. 若二叉樹非空:
    ①先序遍歷左子樹;
    ②先序遍歷右子樹;
    ③訪問根結點。

實現代碼:

typedef struct BiTNode{ElemType data;struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;//后序遍歷
void PostOrder(BiTree T){if(T!=NULL){PostOrder(T->lchild);  //遞歸遍歷左子樹PostOrder(T->rchild);  //遞歸遍歷右子樹visit(T);              //訪問根結點}
}

第三次被訪問的點

二叉樹的層序遍歷

算法思想:

算法思想:

  1. 初始化一個輔助隊列
  2. 根結點入隊
  3. 若隊列非空,則隊頭結點出隊,訪問該結點,并將其左、右孩子插入隊尾(如果有的話)
  4. 重復步驟3直至隊列為空

實現代碼:

//二叉樹的結點(鏈式存儲)
typedef struct BiTNode{char data;struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;//鏈式隊列結點
typedef struct LinkNode{BiTNode * data;struct LinkNode *next;
}LinkNode;typedef struct{LinkNode *front,*rear; //隊頭隊尾
}LinkQueue;//層序遍歷
void LevelOrder(BiTree T){LinkQueue Q;InitQueue(Q);              //初始化輔助隊列BiTree p;EnQueue(Q,T);              //將根結點入隊while(!IsEmpty(Q)){        //隊列不空則循環DeQueue(Q, p);         //隊頭結點出隊visit(p);              //訪問出隊結點if(p->lchild!=NULL)EnQueue(Q,p->lchild); //左孩子入隊if(p->rchild!=NULL)EnQueue(Q,p->rchild); //右孩子入隊}
}

? 存指針而不是結點

    BiTNode * data;

由遍歷序列構造二叉樹

  • 一個中序遍歷序列可能對應多種二叉樹形態

  • 一個前序遍歷序列可能對應多種二叉樹形態

  • 一個后序遍歷序列可能對應多種二叉樹形態

  • 一個層序遍歷序列可能對應多種二叉樹形態

SO : 若只給出一顆二叉樹的前/中/后/層 序遍歷序列中的一種 ,不能唯一確定一顆二叉樹

前序 + 中序遍歷序列
  • 前序遍歷:根結點、前序遍歷左子樹、前序遍歷右子樹

前序遍歷序列:

根結點 左子樹的前序遍歷序列 右子樹的前序遍歷序列

  • 中序遍歷:中序遍歷左子樹、根結點、中序遍歷右子樹

中序遍歷序列:

左子樹的中序遍歷序列 根結點 右子樹的中序遍歷序列

前序遍歷序列: A D B C E

中序遍歷序列: B D C A E

得出的二叉樹:

A
D
E
B
C
后序 + 中序遍歷序列
  • 后序遍歷:前序遍歷左子樹、前序遍歷右子樹、根結點

后序遍歷序列:

左子樹的后序遍歷序列 右子樹的后序遍歷序列 根結點

  • 中序遍歷:中序遍歷左子樹、根結點、中序遍歷右子樹

中序遍歷序列

左子樹的中序遍歷序列 根結點 右子樹的中序遍歷序列

后序遍歷序列: E F A H C I G B D

中序遍歷序列: E A F D H C B G I

得出的二叉樹:

D
A
B
E
F
C
G
H
I
層序 + 中序遍歷序列
  • 層序遍歷序列

    根結點 左子樹的根 右子樹的根

  • 中序遍歷序列

    左子樹的中序遍歷序列 根結點 右子樹的中序遍歷序列

層序遍歷序列:A B C D E

中序遍歷序列:A C B E D

得出的二叉樹:

在這里插入圖片描述

KEY:找到樹的根節點,并根據中序序列劃分左右子樹,再找到左右子樹根結點

二叉樹的中序遍歷(缺點):

Q1:如何找到指定結點 P 在中序遍歷序列中的前驅?

Q2 : 如何找到 p 的中序后繼?

思路:從根節點出發,重新進行一次中序遍歷,指針 q 記錄當前訪問的結點,指針 pre 記錄上一個被訪問的結點

1.當 q == p 時,pre 為前驅

2.當 pre == p 時,q 為后繼

缺點:

找前驅、后繼很不方便:遍歷操作必須從根開始

中序線索二叉樹

中序遍歷序列:D G B E A F C

在這里插入圖片描述

  • 前驅線索(由左孩子指針充當 —— > 紅色線
  • 后繼線索(由右孩子指針充當)—— > 綠色線

線索鏈表代碼實現:

//線索二叉樹結點
typedef struct ThreadNode{ElemType data;struct ThreadNode *lchild,*rchild;int ltag,rtag;      //左、右線索標志
}ThreadNode,*ThreadTree;
  • tag == 0,表示指針指向孩子
    tag ==1,表示指針是“線索”

  • 先序、后序同理

中序線索化

實現代碼

// 線索二叉樹結點結構定義
typedef struct ThreadNode{ElemType data;  struct ThreadNode *lchild,*rchild;  int ltag,rtag; 
}ThreadNode,*ThreadTree;// 全局變量 pre,指向當前訪問結點的前驅
ThreadNode *pre=NULL;  // 中序遍歷二叉樹并進行線索化
void InThread(ThreadTree T){if(T!=NULL){InThread(T->lchild);visit(T); InThread(T->rchild);  }
}// 訪問結點函數(實際處理線索化邏輯)
void visit(ThreadNode *q) {// 左子樹為空,建立前驅線索if(q->lchild==NULL){ q->lchild=pre;q->ltag=1;}// 前驅存在且前驅的右孩子為空,建立前驅結點的后繼線索if(pre!=NULL&&pre->rchild==NULL){ pre->rchild=q;  pre->rtag=1;}pre=q;  // 更新pre為當前結點
}// 封裝中序線索化的入口函數,統一初始化pre并處理最終結點
void CreateInThread(ThreadTree T){pre=NULL;  // 初始化為NULLif(T!=NULL){  InThread(T); // 處理遍歷的最后一個結點:若其右孩子為空,標記為線索if(pre->rchild==NULL){ pre->rtag=1;  }}
}

先序線索化

  • 先序線索化中,注意處理愛滴魔力轉圈圈問題,當 ltag == 0時,才能對左子樹先序線索化

實現代碼;

// 線索二叉樹結點結構定義
typedef struct ThreadNode{ElemType data;struct ThreadNode *lchild, *rchild;int ltag, rtag;
}ThreadNode, *ThreadTree;// 全局變量 pre,指向當前訪問結點的前驅
ThreadNode *pre = NULL;  // 先序遍歷二叉樹,一邊遍歷一邊線索化
void PreThread(ThreadTree T){if(T != NULL){visit(T);  // 先處理根節點(執行線索化核心邏輯)// lchild 不是前驅線索(即 ltag == 0 時,說明是真實孩子,遞歸處理左子樹)if (T->ltag == 0)  PreThread(T->lchild);  PreThread(T->rchild);  // 遞歸處理右子樹}
}// 訪問結點函數(實際進行線索化操作)
void visit(ThreadNode *q) {// 左子樹為空,建立前驅線索if(q->lchild == NULL){  q->lchild = pre;q->ltag = 1;}// 前驅存在且前驅的右孩子為空,建立前驅結點的后繼線索if(pre != NULL && pre->rchild == NULL){  pre->rchild = q;  pre->rtag = 1;}pre = q;  // 更新 pre 為當前結點,為下一個結點做準備
}// 先序線索化二叉樹的入口函數,統一初始化 pre 并處理最后一個結點
void CreatePreThread(ThreadTree T){pre = NULL;  // pre 初始化為 NULLif(T != NULL){  // 非空二叉樹才進行線索化PreThread(T);  // 調用先序線索化遞歸函數// 處理遍歷的最后一個結點:若其右孩子為空,標記為線索if (pre->rchild == NULL)  pre->rtag = 1;  }
}

后序線索化

實現代碼:

// 線索二叉樹結點結構(需提前定義 ElemType,如 typedef int ElemType; )
typedef struct ThreadNode {ElemType data;struct ThreadNode *lchild, *rchild;int ltag, rtag;  // 0: 指向孩子,1: 線索
} ThreadNode, *ThreadTree;// 全局變量:指向當前訪問結點的前驅
ThreadNode *pre = NULL;  // 后序遍歷 + 線索化(遞歸邏輯:左 → 右 → 根)
void PostThread(ThreadTree T) {if (T != NULL) {PostThread(T->lchild);  // 后序遍歷左子樹PostThread(T->rchild);  // 后序遍歷右子樹visit(T);  // 訪問根節點(執行線索化操作)}
}// 訪問結點函數(處理線索化邏輯)
void visit(ThreadNode *q) {// 左子樹為空 → 建立前驅線索if (q->lchild == NULL) {  q->lchild = pre;q->ltag = 1;}// 前驅存在且其右孩子為空 → 建立后繼線索if (pre != NULL && pre->rchild == NULL) {  pre->rchild = q;  pre->rtag = 1;}pre = q;  // 更新前驅為當前結點
}// 后序線索化入口函數(初始化 + 處理最后結點)
void CreatePostThread(ThreadTree T) {pre = NULL;  // 初始化前驅if (T != NULL) {  // 非空樹才線索化PostThread(T);  // 調用后序線索化// 處理遍歷的最后一個結點(根結點)if (pre->rchild == NULL) {  pre->rtag = 1;  }}
}

中序線索二叉樹找中序后繼

在中序線索二叉樹中找到指定結點 * p 的中序后繼 next

  1. 若 p->rtag == 1,則 next = p->rchild
  2. 若 p->rtag == 0

next = p 的右子樹中最左下結點

實現代碼:

// 找到以 p 為根的子樹中,第一個被中序遍歷的結點
ThreadNode *Firstnode(ThreadNode *p){// 循環找到最左下結點(不一定是葉結點)while(p->ltag==0) p=p->lchild;  return p;
}// 在中序線索二叉樹中找到結點 p 的后繼結點
ThreadNode *Nextnode(ThreadNode *p){// 右子樹中最左下結點if(p->rtag==0) return Firstnode(p->rchild);  else return p->rchild;  // rtag==1 直接返回后繼線索
}
  • 對中序線索二叉樹進行中序遍歷(利用線索實現的非遞歸算法)
void Inorder(ThreadNode *T){for(ThreadNode *p=Firstnode(T);p!=NULL; p=Nextnode(p))visit(p);
}

空間復雜度O(1)

中序線索二叉樹找中序前驅

在中序線索二叉樹中找到指定結點 * p 的中序前驅 pre

  1. 若 p->ltag == 1,則 pre = p->lchild
  2. 若 p->ltag == 0

pre = p 的左子樹中最右下結點

實現代碼:

// 找到以 p 為根的子樹中,最后一個被中序遍歷的結點
ThreadNode *Lastnode(ThreadNode *p){// 循環找到最右下結點(不一定是葉結點)while(p->rtag==0) p=p->rchild;  return p;
}// 在中序線索二叉樹中找到結點 p 的前驅結點
ThreadNode *Prenode(ThreadNode *p){// 左子樹中最右下結點if(p->ltag==0) return Lastnode(p->lchild);  else return p->lchild;  // ltag==1 直接返回前驅線索
}
  • 對中序線索二叉樹進行逆向中序遍歷
void RevInorder(ThreadNode *T){for(ThreadNode *p=Lastnode(T);p!=NULL; p=Prenode(p))visit(p);
}

中序線索二叉樹找先序后繼

在先序線索二叉樹中找到指定結點 * p 的中序后繼 next

  1. 若 p->rtag == 1,則 pre = p->rchild
  2. 若 p->rtag == 0

假設有左孩子

  • 若 p 有左孩子,則先序后繼為左孩子

先序遍歷 —— 根 左 右
根 (根 左 右) 右

假設沒有左孩子

  • 若 p 沒有左孩子,則先序后繼為右孩子

先序遍歷 —— 根 右
根 (根 左 右)

先序線索二叉樹找先序前驅

在先序線索二叉樹中找到指定結點 * p 的中序前驅 pre

  1. 若 p->ltag == 1,則 pre = p->lchild
  2. 若 p->ltag == 0

在先序遍歷中,左右子樹的結點只可能是根的后繼,不可能是前驅

后序線索二叉樹找后序前驅

在先序線索二叉樹中找到指定結點 * p 的中序前驅 pre

  1. 若 p->ltag == 1,則 pre = p->lchild
  2. 若 p->ltag == 0

假設有右孩子

  • 若 p 有右孩子,則后序前驅為右孩子

后序遍歷 —— 左 右 根
左 (左 右 根) 根

假設沒有右孩子

  • 若 p 沒有右孩子,則后序前驅為左孩子

后序遍歷 —— 左 根
(左 右 根) 根

中序線索二叉樹先序線索二叉樹后序線索二叉樹
找前驅???
找后繼???

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

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

相關文章

【C語言進階】結構體練習:通訊錄

要求: 實現一個通訊錄。 (1)人的信息: 包括姓名、年齡、性別、電話地址。 (2)功能: ①存放一百個人的信息。 ②增加聯系人。 ③刪除指定聯系人。 ④查找指定聯系人。 ⑤修改聯系人。 ⑥排序。 ⑦顯示聯系人。 (3)文件: ①contact.…

緩存三劍客解決方案

緩存三劍客解決方案 1.緩存雪崩 定義: 大量緩存數據在同一時間點集體失效,導致所有請求直接穿透到數據庫,引發數據庫瞬時高負載甚至崩潰。 解決方案: 設置過期隨機值,避免大量緩存同時失效。 // 緩存雪崩防護&#xff…

HTML 頁面禁止縮放功能

頁面禁止縮放 代碼如下&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8"><meta name"viewport" content"widthdevice-width, initial-scale1, shrink-to-fitno, maximum-scale1.0, us…

在github上搭建自己主頁

主要是這篇博客進行一些補充。 第一步照做就行 首先是第二步 克隆倉庫到本地 先下載一個git&#xff0c;電腦創建一個新文件夾&#xff0c;然后 git clone xxxxx 注意即使你使用了代理&#xff0c;這里大概率也會報錯&#xff0c;Failed to connect to github.com port 443 …

Laravel 框架NOAUTH Authentication required 錯誤解決方案-優雅草卓伊凡

Laravel 框架NOAUTH Authentication required 錯誤解決方案-優雅草卓伊凡NOAUTH Authentication required 錯誤這個錯誤通常出現在以下幾種情況&#xff1a;Redis 認證問題&#xff1a;如果你的應用使用了 Redis 且配置了密碼API 認證問題&#xff1a;請求需要認證的 API 端點但…

kafka生產端和消費端的僵尸實例以及解決辦法

目錄 一 生產端僵尸 1.1 原因 1.2 問題 1.3解決辦法 1.4 案例 1.4.1 案例1&#xff1a;生產者崩潰后重啟 (同一 transactional.id) 1.4.2 案例2&#xff1a;短暫網絡分區導致的腦裂 1.4.3 案例3&#xff1a;正確 - 解決僵尸 1.4.4 案例4&#xff1a;錯誤 - 無法解決僵…

國產電科金倉數據庫金倉KES V9 2025:AI時代的數據庫融合標桿

國產電科金倉數據庫金倉KES V9 2025&#xff1a;AI時代的數據庫融合標桿 在AI技術迅猛發展的今天&#xff0c;企業數據管理面臨著前所未有的挑戰&#xff1a;異構數據庫兼容難題、多數據模型融合需求、高并發場景性能瓶頸、跨中心容災壓力……這些痛點如同數據流轉的大問題&am…

【STM32】關于STM32F407寫Flash失敗問題的解決辦法

問題描述 在使用正點原子的STM32F407寫flash例程時&#xff0c;發現STMFLASH_Write函數沒辦法寫入數據到flash&#xff0c;原始代碼輸入下&#xff1a; 隨后對每一行代碼的結果進行分析&#xff0c;發現87行的“FLASH_ProgramWord(WriteAddr,*pBuffer)”返回值是7&#xff0c;一…

CUDA與RISC-V的融合:打破架構霸權,重塑AI計算未來

當x86和Arm統治數據中心十余年后,一家GPU巨頭正悄悄將十億顆RISC-V核心嵌入其系統。如今,它決定拆除CPU架構的圍墻。 2025年7月,上海張江科學會堂。英偉達硬件工程副總裁Frans Sijstermanns在第五屆RISC-V中國峰會上宣布:英偉達正式啟動CUDA向RISC-V架構的移植工作。 這個…

微信二維碼掃描登錄流程詳解

二維碼掃描登錄流程細節&#xff08;項目經驗&#xff09; 1&#xff1a; 獲取二維碼信息 PC會優先存放服務器生成的唯一密鑰&#xff1a; 比如 source、secret 以密文形式存儲大致發送字段&#xff1a; sourcesecretmac(mac 地址) 服務器生成 二維碼信息&#xff1a;二維碼字符…

日本上市IT企業|8月125日將在大連舉辦赴日it招聘會

株式會社GSD的核心戰略伙伴貝斯株式會社&#xff0c;將于2025年8月25日在大連香格里拉大酒店商務會議室隆重舉辦赴日技術人才專場招聘會。本次招聘會面向全國范圍內的優秀IT人才&#xff0c;旨在為貝斯株式會社東京本社長期發展招募優質的系統開發與管理人才。招聘計劃&#xf…

Python 數據分析與可視化:從基礎到進階的技術實現與優化策略

數據分析與可視化是數據科學領域的核心技能,Python 憑借其豐富的庫生態和靈活的編程范式,成為該領域的首選工具。本文將系統講解 Python 數據分析與可視化的技術棧實現,從基礎操作到性能優化,結合實戰場景提供可復用的解決方案。 數據分析核心庫技術解析 Pandas 數據處理…

Rust Web 全棧開發(十):編寫服務器端 Web 應用

Rust Web 全棧開發&#xff08;十&#xff09;&#xff1a;編寫服務器端 Web 應用Rust Web 全棧開發&#xff08;十&#xff09;&#xff1a;編寫服務器端 Web 應用創建成員庫&#xff1a;webappmodelshandlersrouterserrorsmodsvrstaticteachers.htmlregister.htmlbootstrap.m…

每日面試題11:JVM

深入理解JVM&#xff1a;Java的“心臟”如何驅動程序運行&#xff1f;為什么需要JVM&#xff1f;你是否想過&#xff0c;為什么用Java寫的程序&#xff0c;能在Windows、Linux、macOS上“無縫運行”&#xff1f;為什么開發者無需為不同操作系統重寫代碼&#xff1f;這背后的核心…

Linux網絡信息(含ssh服務和rsync)

73.telnet&#xff1a;測試端口連通性用法&#xff1a;telnet 主機名或IP 端口號測試目標主機的指定端口是否開放&#xff0c;檢查網絡服務連通性。eg&#xff1a;telnet www.baidu.com 80# 說明&#xff1a;# - 如果連接成功&#xff0c;顯示 "Connected to ..."。…

【PTA數據結構 | C語言版】我愛背單詞

本專欄持續輸出數據結構題目集&#xff0c;歡迎訂閱。 文章目錄題目代碼題目 作為一個勤奮的學生&#xff0c;你在閱讀一段英文文章時&#xff0c;是否希望有個程序能自動幫你把沒有背過的生詞列出來&#xff1f;本題就請你實現這個程序。 輸入格式&#xff1a; 輸入第 1 行給…

如何使用電腦連接小米耳機(紅米 redmi耳機)

如何使用電腦連接小米&#xff08;紅米 redmi&#xff09;耳機Redmi耳機連接電腦的具體步驟如下注意事項和常見問題解決方法&#xff1a;Redmi耳機連接電腦的具體步驟如下 打開耳機倉蓋&#xff1a; 首先&#xff0c;打開Redmi耳機的充電倉蓋&#xff0c;但不需要取出耳機。進…

排序算法—交換排序(冒泡、快速)(動圖演示)

目錄 十大排序算法分類?編輯 冒泡排序 算法步驟&#xff1a; 動圖演示&#xff1a; 性能分析&#xff1a; 代碼實現&#xff08;Java&#xff09;&#xff1a; 快速排序&#xff08;挖坑法&#xff09; 算法步驟&#xff1a; 動圖演示&#xff1a; 性能分析&#xff1…

2023 年 5 月青少年軟編等考 C 語言八級真題解析

目錄 T1. 道路 思路分析 T2. Rainbow 的商店 思路分析 T3. 冰闊落 I 思路分析 T4. 青蛙的約會 思路分析 T1. 道路 題目鏈接:SOJ D1216 N N N 個以 1 ~ N 1 \sim N 1~N 標號的城市通過單向的道路相連,每條道路包含兩個參數:道路的長度和需要為該路付的通行費(以金幣的數…

【vue-4】深入理解 Vue 3 中的 v-for 指令

Vue.js 作為現代前端框架的代表之一&#xff0c;其模板指令系統提供了強大的數據綁定和渲染能力。其中&#xff0c;v-for 指令是 Vue 中最常用且最重要的指令之一&#xff0c;它允許我們基于數據源循環渲染元素或組件。在 Vue 3 中&#xff0c;v-for 保留了一貫的簡潔語法&…