AVL 樹

AVL樹的概念

二叉搜索樹雖可以縮短查找的效率,但如果數據有序或接近有序二叉搜索樹將退化為單支樹,查找元素相當于在順序表中搜索元素,效率低下。因此,兩位俄羅斯的數學家G.M.Adelson-Velskii和E.M.Landis在1962年
發明了一種解決上述問題的方法:當向二叉搜索樹中插入新結點后,如果保證每個結點的左右子樹高度之差的絕對值不超過1(需要對樹中的結點進行調整),即可降低樹的高度,從而減少平均搜索長度

一棵AVL樹或者是空樹,或者是具有以下性質的二叉搜索樹:

它的左右子樹都是AVL樹
左右子樹高度之差(簡稱平衡因子)的絕對值不超過1(-1/0/1)

節點的平衡因子=右子樹的高度-左子樹的高度

例如:
下圖的二叉搜索樹的每個節點的平衡因子的 絕對值都小于2,并且每個節點的子樹也都是AVL樹
在這里插入圖片描述

AVL樹的定義

AVL樹是一種特殊的二叉搜索樹,它具有高度的平衡,所以為了在插入過程中的各個節點的平衡因子的更新,我們在定義AVL樹的節點結構的同時要帶上一個節點的雙親結點parent

template<class T>
struct AVLTreeNode
{AVLTreeNode(const T& data): _left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _bf(0){}AVLTreeNode<T>* _left;   // 該節點的左孩子AVLTreeNode<T>* _right;  // 該節點的右孩子AVLTreeNode<T>* _parent; // 該節點的雙親T _data;int _bf;                  // 該節點的平衡因子
};
AVL樹的插入

AVL樹的插入是一個難點,它分為好幾種情況,其實AVL樹的插入也就是在二叉搜索樹中插入新節點,但是由于他引入了平衡因子,需要更新,所以這里的插入節點就比較麻煩,她一共分為兩步:

1 插入節點
2 更新節點的平衡因子

為什么要更新節點的平衡因子呢?

簡單地舉個例子:
如圖所示,我將一個新節點插入0的左孩子節點的位置,那么以3為節點的這顆子樹的高度差不就會超過1了嗎,他的左子樹的高度插入新節點后為3,而右子樹為1,這就不符合AVL樹的性質了,所以我們需要經過一些操作來更新平衡因子
在這里插入圖片描述

這里大家需要注意一個規則:
新節點如果是插入后他的parent的左側,那么他的平衡因子默認是+1
反之插入他的右側就是默認-1

那么在插入節點后,各個插入節點的parent一共就有三種情況了:

平衡因子為0
如果parent的平衡因子為0,說明插入之前parent的平衡因子為正負1,插入后被調整成0,此時滿足AVL樹的性質,插入成功

平衡因子為正負1
如果parent的平衡因子為正負1,說明插入前pParent的平衡因子一定為0,插入后被更新成正負1,此時以parent為根的樹的高度增加,需要繼續向上更新,防止部分節點的左右子樹高度差超過1
平衡因子為正負2
如果parent的平衡因子為正負2,則pParent的平衡因子違反平衡樹的性質,需要對其進行旋轉處理,旋轉處理之后插入成功

至于旋轉的情況我們待會分析,我們先將插入節點的代碼的主要框架構造出來:
這樣一個簡單的框架就構造出來了

template<class T>
struct AVLTreeNode
{AVLTreeNode<T>* _left;   // 該節點的左孩子AVLTreeNode<T>* _right;  // 該節點的右孩子AVLTreeNode<T>* _parent; // 該節點的雙親T _data;int _bf;                  // 該節點的平衡因子AVLTreeNode(const T& data): _left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _bf(0){}
};
template<class T>
class AVLTree
{typedef AVLTreeNode<T> Node;
public:bool insert(const T& data){if (_root == nullptr){_root = new Node(data);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_data < data){parent = cur;cur = cur->_right;}else if (cur->_data > data){parent = cur;cur = cur->_left;}else{return false;}cur = new Node(data);if (parent->_data > data){parent->_left = cur;}else{parent->_right = cur;}while (parent){//左邊++if (cur == parent->_left){parent->_bf--;}//右邊--else{parent->_bf++;}//parent的平衡因子等于0,插入成功if (parent->_bf == 0){break;}//parent的平衡因子等于1或者-1,繼續向上更新else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){//需要進行旋轉}else{assert(false);}}}}private:Node* _root;
};

下面我們就具體分析幾種旋轉的情況

AVL樹的旋轉

如果在一棵原本是平衡的AVL樹中插入一個新節點,可能造成不平衡,此時必須調整樹的結構,使之平衡化。根據節點插入位置的不同,AVL樹的旋轉分為四種:

1. 新節點插入較高左子樹的左側—左左:右單旋
下圖中的h可以時0 1 2三種,分別代表了這三個子樹的高度,無論他是等于0 1 還是2時他們都可以滿足AVL樹的要求
在這里插入圖片描述
可以看到,這種情況就是parent的平衡因子等于-2,cur的平衡因子等于-1
左旋函數如下:

void RotateR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;//防止sublr為空if(subLR)subLR->_parent = parent;//記錄祖父位置Node* pparent = parent->_parent;subL->_right = parent;parent->_parent = subL;//如果父親是根節點if (parent == _root){_root = subL;subL->_parent = nullptr;}//parent不是根節點,那么祖父就會成為subl的parentelse{if (pparent->_left == parent){pparent->_left = subL;subL->_parent = pparent;}else{pparent->_right = subL;subL->_parent = pparent;}}//旋轉后parent和subl的 平衡因子都會更新為0parent->_bf = subL->_bf = 0;
}

2. 新節點插入較高右子樹的右側—右右:左單旋
實現及情況考慮可參考右單旋。
在這里插入圖片描述

void RotateL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;subR->_left = parent;Node* pparent = parent->_parent;if (subRL)subRL->_parent = parent;if (_root == parent){_root = subR;subR->_parent == nullptr;}else{if (pparent->_left == parent){pparent->_left = subR;subR->_parent = pparent;}else{pparent->_right = subR;subR->_parent = pparent;}}parent->_bf = subR->_bf = 0;
}

3. 新節點插入較高左子樹的右側—左右:先左單旋再右單旋
在這里插入圖片描述
將雙旋變成單旋后再旋轉,即:先對30進行左單旋,然后再對90進行右單旋,旋轉完成后再考慮平衡因子的更新。
直接復用即可:
由于博主能力有限,所以放入代碼大家仔細理解

void RotateLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;RotateL(parent->_left);RotateR(parent);int bf = subLR->_bf;//sublr就是新增節點if (bf == 0){parent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}//sublr左子樹新增節點else if (bf == -1){parent->_bf = 1;subL->_bf = 0;subLR->_bf = 0;}//sublr右子樹新增節點else if (bf == 1){parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else{assert(false);}
}

4. 新節點插入較高右子樹的左側—右左:先右單旋再左單旋
在這里插入圖片描述

void RotateRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);//subrl這個點為新增點if (bf == 0){parent->_bf = subR->_bf = subRL->_bf = 0;}//subrl的左子樹新增else if (bf == -1){parent->_bf = 0;subRL->_bf = 0;subR->_bf = 1;}//subrl的右子樹新增else if (bf == 1){parent->_bf = -1;subRL->_bf = 0;subR->_bf = 0;}else{assert(false);}
}

根據各種情況我們做了總結:

假如以parent為根的子樹不平衡,即parent的平衡因子為2或者-2,分以下情況考慮

  1. parent的平衡因子為2,說明parent的右子樹高,設parent的右子樹的根為subR,當subR的平衡因子為1時,執行左單旋當subR的平衡因子為-1時,執行右左雙旋
  2. parent的平衡因子為-2,說明parent的左子樹高,設parent的左子樹的根為subL,當subL的平衡因子為-1是,執行右單旋,當subL的平衡因子為1時,執行左右雙旋旋轉完成后,原parent為根的子樹個高度降低,已經平衡,不需要再向上更新。

所以我們可以補全上面的插入節點的代碼了:

bool insert(const T& data)
{if (_root == nullptr){_root = new Node(data);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_data < data){parent = cur;cur = cur->_right;}else if (cur->_data > data){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(data);if (parent->_data > data){parent->_left = cur;}else{parent->_right = cur;}while (parent){//左邊++if (cur == parent->_left){parent->_bf--;}//右邊--else{parent->_bf++;}//parent的平衡因子等于0,插入成功if (parent->_bf == 0){break;}//parent的平衡因子等于1或者-1,繼續向上更新else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){//需要進行旋轉if (parent->_bf == 2 && cur->_bf == 1){RotateL(parent);}else if (parent->_bf == 2 && cur->_bf == -1){RotateRL(parent);}else if (parent->_bf == -2 && cur->_bf == -1){RotateR(parent);}else if (parent->_bf == -2 && cur->_bf == 1){RotateLR(parent);}break;}else{assert(false);}}return true;
}
AVL樹的驗證

AVL樹是在二叉搜索樹的基礎上加入了平衡性的限制,因此要驗證AVL樹,可以分兩步:

1. 驗證其為二叉搜索樹
如果中序遍歷可得到一個有序的序列,就說明為二叉搜索樹
2. 驗證其為平衡樹每個節點子樹高度差的絕對值不超過1(注意節點中如果沒有平衡因子)節點的平衡因子是否計算正確

我們可以用一個函數來判斷即可:
首先要有一個計算樹的高度的函數
然后判斷他們的子樹的高度差的絕對值是否在2以內,并且他們的子樹也要是AVL樹

int Height(Node* root)
{if (root == nullptr){return 0;}int leftheight = Height(root->_left);int rightheight = Height(root->_right);return leftheight > rightheight ? leftheight + 1 : rightheight + 1;
}bool isbalance()
{return _isbalance(_root);
}bool _isbalance(Node* root)
{if (root == nullptr)return true;int leftheight = Height(root->_left);int rightheight = Height(root->_right);if (rightheight - leftheight != root->_bf){cout << root->_data << "平衡因子異常" << endl;return false;}return abs(rightheight - leftheight) < 2&& _isbalance(root->_left)&& _isbalance(root->_right);
}

我們還可以用中序遍歷打印:

void inorder()
{_inorder(_root);cout << endl;
}void _inorder(Node* root)
{if (root == nullptr){return;}_inorder(root->_left);cout << root->_data << " ";_inorder(root->_right);
}

在這里插入圖片描述
完整代碼如下:

#include<iostream>
#include<assert.h>
using namespace std;
template<class T>
struct AVLTreeNode
{AVLTreeNode<T>* _left;   // 該節點的左孩子AVLTreeNode<T>* _right;  // 該節點的右孩子AVLTreeNode<T>* _parent; // 該節點的雙親T _data;int _bf;                  // 該節點的平衡因子AVLTreeNode(const T& data): _left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _bf(0){}
};
template<class T>
class AVLTree
{typedef AVLTreeNode<T> Node;
public:bool insert(const T& data){if (_root == nullptr){_root = new Node(data);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_data < data){parent = cur;cur = cur->_right;}else if (cur->_data > data){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(data);if (parent->_data > data){parent->_left = cur;}else{parent->_right = cur;}while (parent){//左邊++if (cur == parent->_left){parent->_bf--;}//右邊--else{parent->_bf++;}//parent的平衡因子等于0,插入成功if (parent->_bf == 0){break;}//parent的平衡因子等于1或者-1,繼續向上更新else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){//需要進行旋轉if (parent->_bf == 2 && cur->_bf == 1){RotateL(parent);}else if (parent->_bf == 2 && cur->_bf == -1){RotateRL(parent);}else if (parent->_bf == -2 && cur->_bf == -1){RotateR(parent);}else if (parent->_bf == -2 && cur->_bf == 1){RotateLR(parent);}break;}else{assert(false);}}return true;}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;//防止sublr為空if(subLR)subLR->_parent = parent;//記錄祖父位置Node* pparent = parent->_parent;subL->_right = parent;parent->_parent = subL;//如果父親是根節點if (parent == _root){_root = subL;subL->_parent = nullptr;}//parent不是根節點,那么祖父就會成為subl的parentelse{if (pparent->_left == parent){pparent->_left = subL;subL->_parent = pparent;}else{pparent->_right = subL;subL->_parent = pparent;}}//旋轉后parent和subl的 平衡因子都會更新為0parent->_bf = subL->_bf = 0;}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;subR->_left = parent;Node* pparent = parent->_parent;if (subRL)subRL->_parent = parent;if (_root == parent){_root = subR;subR->_parent == nullptr;}else{if (pparent->_left == parent){pparent->_left = subR;subR->_parent = pparent;}else{pparent->_right = subR;subR->_parent = pparent;}}parent->_bf = subR->_bf = 0;}void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;RotateL(parent->_left);RotateR(parent);int bf = subLR->_bf;//sublr就是新增節點if (bf == 0){parent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}//sublr左子樹新增節點else if (bf == -1){parent->_bf = 1;subL->_bf = 0;subLR->_bf = 0;}//sublr右子樹新增節點else if (bf == 1){parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else{assert(false);}}void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);//subrl這個點為新增點if (bf == 0){parent->_bf = subR->_bf = subRL->_bf = 0;}//subrl的左子樹新增else if (bf == -1){parent->_bf = 0;subRL->_bf = 0;subR->_bf = 1;}//subrl的右子樹新增else if (bf == 1){parent->_bf = -1;subRL->_bf = 0;subR->_bf = 0;}else{assert(false);}}int Height(Node* root){if (root == nullptr){return 0;}int leftheight = Height(root->_left);int rightheight = Height(root->_right);return leftheight > rightheight ? leftheight + 1 : rightheight + 1;}bool isbalance(){return _isbalance(_root);}bool _isbalance(Node* root){if (root == nullptr)return true;int leftheight = Height(root->_left);int rightheight = Height(root->_right);if (rightheight - leftheight != root->_bf){cout << root->_data << "平衡因子異常" << endl;return false;}return abs(rightheight - leftheight) < 2&& _isbalance(root->_left)&& _isbalance(root->_right);}void inorder(){_inorder(_root);cout << endl;}void _inorder(Node* root){if (root == nullptr){return;}_inorder(root->_left);cout << root->_data << " ";_inorder(root->_right);}private:Node* _root=nullptr;
};

好了,今天的分享到這里就結束了,感謝大家的支持!

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

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

相關文章

k8s筆記26--快速實現prometheus監控harbor

k8s筆記26--快速實現prometheus監控harbor 簡介采集指標&配置grafana面板采集指標配置grafana面板 說明 簡介 harbor是當前最流行的開源容器鏡像倉庫項目&#xff0c;被大量IT團隊廣泛應用于生產、測試環境的項目中。本文基于Harbor、Prometheus、Grafana介紹快速實現監控…

3. 臺階問題

數樓梯 題目描述 樓梯有 N N N 階&#xff0c;上樓可以一步上一階&#xff0c;也可以一步上二階。 編一個程序&#xff0c;計算共有多少種不同的走法。 輸入格式 一個數字&#xff0c;樓梯數。 輸出格式 輸出走的方式總數。 樣例 #1 樣例輸入 #1 4樣例輸出 #1 5提示…

FPGA之帶有進位邏輯的加法運算

module ADDER&#xff08; input [5&#xff1a;0]A&#xff0c; input [5&#xff1a;0]B&#xff0c;output[6&#xff1a;0]Q &#xff09;&#xff1b; assign Q AB&#xff1b; endmodule 綜合結果如下圖所示&#xff1a; 使用了6個Lut&#xff0c;&#xff0c;6個LUT分布…

詳細介紹如何用windows11自帶Hyper-V安裝虛擬機

通過系統自帶的hyper-v安裝windows11&#xff0c;舒服又愜意&#xff0c;相比用第三方虛擬機軟件速度快很多。 硬件準備 1、對于電腦自帶的虛擬機Hyper-V&#xff0c;不是每種電腦系統版本都帶著的。我們先要確定您的系統符合 Hyper-V 的最低要求。我們跟著下面的步驟來執行&…

鴻蒙開發相關知識(四)【數據持久化(用戶首選項、關系型數據庫)、通知(基礎通知、進度條通知、通知意圖)】

文章目錄 一、數據持久化1、用戶首選項&#xff08;1&#xff09;語法說明&#xff08;2&#xff09;完整代碼示例 2、關系型數據庫&#xff08;1&#xff09;初始化數據庫&#xff08;2&#xff09;增刪改數據&#xff08;3&#xff09;查詢數據&#xff08;4&#xff09;完整…

《2023年勒索軟件攻擊態勢報告》

獲取方式&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1zd-yVsuGwJADyyGNFR_TIQ?pwd2lo0 提取碼&#xff1a;2lo0

探索數據結構:解鎖計算世界的密碼

?? 歡迎大家來到貝蒂大講堂?? &#x1f388;&#x1f388;養成好習慣&#xff0c;先贊后看哦~&#x1f388;&#x1f388; 所屬專欄&#xff1a;數據結構與算法 貝蒂的主頁&#xff1a;Betty‘s blog 前言 隨著應用程序變得越來越復雜和數據越來越豐富&#xff0c;幾百萬、…

600萬訂單每秒Disruptor +SpringBoot,如何解決消息不丟失?

尼恩說在前面 在40歲老架構師 尼恩的讀者交流群(50)中&#xff0c;最近有小伙伴拿到了一線互聯網企業如得物、阿里、滴滴、極兔、有贊、shein 希音、百度、網易的面試資格&#xff0c;遇到很多很重要的面試題&#xff1a; Disruptor 官方說能達到每秒600w OPS訂單處理能力&…

Java——Object

1.Object萬類之祖 1.1 Object類型的概述 Object類是所有類型的頂層父類&#xff0c;所有類型的直接或者間接的父類&#xff1b;所有的類型中都含有Object類中的所有方法。 隨意定義一個類型,不手動顯式定義其父類&#xff0c;那么這個類的父類就是Object類 public Object() …

【C語言】指針初階2.0版本

這篇博文我們來繼續學習指針的其他內容 指針2.0 傳值調用與傳址調用傳值調用傳址調用 一維數組與指針理解數組名使用指針深入理解一維數組 二級指針指針數組二維數組與指針 傳值調用與傳址調用 在開始之前&#xff0c;我們需要先了解這個概念&#xff0c;后面才能夠正常的學習…

利用 Python 抓取數據探索汽車市場趨勢

一、引言 隨著全球對環境保護意識的增強和技術的進步&#xff0c;新能源汽車作為一種環保、高效的交通工具&#xff0c;正逐漸受到人們的關注和青睞。在這個背景下&#xff0c;對汽車市場的數據進行分析和研究顯得尤為重要。 本文將介紹如何利用 Python 編程語言&#xff0c;結…

VSCode上搭建C/C++開發環境(vscode配置c/c++環境)Windows系統---保姆級教程

引言勸退 VSCode&#xff0c;全稱為Visual Studio Code&#xff0c;是由微軟開發的一款輕量級&#xff0c;跨平臺的代碼編輯器。大家能來搜用VSCode配置c/c&#xff0c;想必也知道VSCode的強大&#xff0c;可以手握一個VSCode同時編寫如C&#xff0c;C&#xff0c;C#&#xff…

微服務day02-Ribbon負載均衡與Nacos安裝與入門

一.Ribbon負載均衡 在上一節中&#xff0c;我們通過在RestTemplte實例中加上了注解 LoadBalanced,表示將來由RestTemplate發起的請求會被Ribbon攔截和處理&#xff0c;實現了訪問服務時的負載均衡&#xff0c;那么他是如何實現的呢&#xff1f; 1.1 Ribbon負載均衡的原理 Rib…

鏈表的歸并排序-LeetCode(Python版)

雙指針歸并排序&#xff01;圖解排序鏈表&#xff01;-知乎 class ListNode(object):def __init__(self, val0, nextNone):self.val valself.next nextclass Solution(object):def find_mid(self, head): # 快慢指針slow, fast head, headwhile fast.next and fast.next.n…

linux 硬盤存儲剩余容量自動化監控+報警通知

linux 硬盤存儲剩余容量自動化監控報警通知 編寫shell腳本 #!/bin/bash# 獲取系統存儲大小&#xff08;單位為GB&#xff09; storage_size$(df -h / | awk NR2 {print $4} | sed s/G//)# 閾值&#xff08;小于10GB觸發報警&#xff09; threshold10# 釘釘機器人 Webhook UR…

LabVIEW非接觸式電阻抗層析成像系統

LabVIEW非接觸式電阻抗層析成像系統 非接觸式電阻抗層析成像&#xff08;NEIT&#xff09;技術以其無輻射、非接觸、響應速度快的特點&#xff0c;為實時監測提供了新的解決方案。基于LabVIEW的電阻抗層析成像系統&#xff0c;實現了數據的在線采集及實時成像&#xff0c;提高…

代碼隨想錄算法訓練營第四十四天|139.單詞拆分、56.攜帶礦石資源

139.單詞拆分 思路&#xff1a;將字符串s看作為背包容量&#xff0c;從字符串中獲取物品&#xff0c;剛好滿足背包容量的過程&#xff0c;因為可以從字符串中多次取值&#xff0c;相當于物品的數量是不限制&#xff0c;這就是一個完全背包的問題&#xff01;這個題有個關鍵點&a…

Python中的windows路徑問題

在Python中處理Windows路徑時,經常會遇到一些特殊的問題。這主要是因為Windows和大多數其他操作系統(如Linux和macOS)使用不同的路徑分隔符。在Windows中,路徑使用反斜杠(\)作為分隔符,而在其他操作系統中,路徑使用正斜杠(/)作為分隔符。 以下是在Python中處理Windo…

Java SE:多線程(Thread)

1. 線程兩個基本概念 并發&#xff1a;即線程交替運行多個指令并行&#xff1a;即多個線程同時運行指令 并發并行不矛盾&#xff0c;兩者可同時發生&#xff0c;即多個線程交替運行指令 2. 多線程3種實現方式 2.1 直接創建線程對象 /*** 方式1&#xff1a;* 1. 創建thread類的…

mybatis plus 深入學習 【Base Mapper】的方法 【IService】的方法

mybatis plus 深入學習 常見注解 1.TableName 描述&#xff1a;表名注解&#xff0c;標識實體類對應的表使用位置&#xff1a;實體類 TableName("sys_user") public class User {private Long id;private String name;private Integer age;private String email;…