數據結構之二叉平衡樹

系列文章目錄

數據結構之ArrayList_arraylist o(1) o(n)-CSDN博客

數據結構之LinkedList-CSDN博客

數據結構之棧_棧有什么方法-CSDN博客

數據結構之隊列-CSDN博客

數據結構之二叉樹-CSDN博客

數據結構之優先級隊列-CSDN博客

常見的排序方法-CSDN博客

數據結構之Map和Set-CSDN博客


目錄

系列文章目錄

前言

一、二叉搜索樹

1. 二叉搜索樹的性質

2. 二叉搜索樹的查詢性能

二、AVL樹

1. AVL 樹的性質

2. AVL樹的節點定義

3. AVL樹節點的插入

?4. AVL樹的驗證

1. 驗證其為二叉搜索樹

2. 驗證其為平衡樹

5. AVL樹的性能分析

三、紅黑樹

1. 紅黑樹的性質

2. 紅黑樹的節點定義

3. 紅黑樹節點的插入

4. 紅黑樹的驗證

四、AVL樹和紅黑樹的比較


前言

本文介紹了兩種自平衡二叉搜索樹:AVL樹和紅黑樹。AVL樹通過保持左右子樹高度差不超過1來實現嚴格平衡,其查詢效率為O(logN),但在插入刪除時需要頻繁旋轉調整。紅黑樹通過顏色規則(無連續紅節點、路徑黑節點數相同)實現近似平衡,最長路徑不超過最短路徑兩倍,雖然查詢效率略低于AVL樹,但插入刪除時旋轉次數較少,實際應用更廣泛。文章詳細闡述了兩者的性質、節點結構、插入操作(含平衡調整邏輯)及驗證方法,并通過性能對比說明AVL樹適合讀多寫少場景,紅黑樹更適合頻繁修改的場景。


一、二叉搜索樹

1. 二叉搜索樹的性質

二叉搜索樹中的左孩子的值都小于根節點的值,右孩子的值都大于根節點的值;

二叉搜索樹的中序遍歷是一個有序數組;

2. 二叉搜索樹的查詢性能

如果在二叉搜索樹中連續插入的值都比之前插入的值大,那么二叉搜索樹會變成一棵右單樹,查詢效率就會從原來的 O(logN) 退化成 O(N);

為了保證二叉搜索樹的查詢效率,就引入了高度平衡的二叉搜索樹,即 AVL 樹;

二、AVL樹

1. AVL 樹的性質

AVL樹是一棵高度平衡的二叉搜索樹,即左右子樹的高度差不超過 1;

2. AVL樹的節點定義

val 表示節點的值;

bf 表示平衡因子,計算方法為 右樹的高度 - 左樹的高度

left 表示左子樹;

right 表示右子樹;

parent 表示父親節點;

public class AVLTree {static class TreeNode{public int val;public int bf;public TreeNode left;public TreeNode right;public TreeNode parent;public TreeNode(int val){this.val = val;}}// 二叉搜索樹的屬性及方法// ......
}

3. AVL樹節點的插入

root 表示 AVL 樹的根節點;

insert(int val): boolean 在 AVL 樹中插入節點;

思路:

1. 如果樹為空,那么新插入的節點就是樹的根節點;

2. 查找

節點的插入方式和二叉搜索樹相同,定義 cur 找要插入節點的位置,parent 指向 cur 的父節點;

如果 cur 的值小于 val,去右子樹找,如果 cur 的值大于 val,去左子樹找找,如果 cur 的值等于 val,說明節點已經存在,不能進行插入,返回 false 即可;?

3. 插入

如果 cur 為空,表示找到了插入位置,如果節點的值小于 parent 的值,插入到 parent 左邊,如果節點的值大于 parent 的值,插入到 parent 的右邊,再讓 cur 重新指向新插入的節點;

4. 修改平衡因子

如果 cur 是 parent 的左子樹,說明插入的節點在 parent 左邊,左子樹的高度增加了,因此 parent 的平衡因子減 1;

如果 cur 是 parent 的右子樹,說明插入的節點在 parent 右邊,右子樹的高度增加了,因此 parent 的平衡因子加 1;

5. 判斷平衡因子

如果修改完 parent 的平衡因子等于 0,表示 parent 這棵樹已經平衡了,同時 0 不會影響整棵樹的平衡,直接返回 true 即可;

如果修改完 parent 的平衡因子等于 1 或者 -1,表示 parent 平衡,但是可能會影響整棵樹的平衡,需要繼續向上調整平衡因子,因此 cur 指向 parent,parent 重新指向 cur 的父節點,繼續向上調整;

6. 樹的調整

繼續向上調整的過程中,如果修改完 parent 的平衡因子等于 2 或者 -2,表示 parent 這棵樹已經不平衡了,此時需要進行旋轉操作,來使得樹重新達到平衡;

如果 parent 的平衡因子等于 2,并且 cur 的平衡因子等于 1,表示 parent 和 cur 子樹的右子樹高度高,此時通過左旋 parent 使樹重新達到平衡;

    private void rotateLeft(TreeNode parent){TreeNode subR = parent.right;TreeNode subRL = subR.left;// 修改四個指向parent.right = subRL;subR.left = parent;if(subRL != null){subRL.parent = parent;}// 修改 parent 的父節點之前,保存 parent 的父節點TreeNode pParent = parent.parent;parent.parent = subR;if(root == parent){root = subR;root.parent = null;}else{if(pParent.left == parent){pParent.left = subR;}else{pParent.right = subR;}}subR.parent = pParent;subR.bf = 0;parent.bf = 0;}

如果 parent 的平衡因子等于 -2,并且 cur 的平衡因子等于 -1,表示 parent 和 cur 子樹的左子樹高度高,此時通過右旋 parent 使樹重新達到平衡;

    private void rotateRight(TreeNode parent){TreeNode subL = parent.left;TreeNode subLR = subL.right;// 修改四個指向parent.left = subLR;subL.right = parent;if(subLR != null){subLR.parent = parent;}// 記錄父節點的父節點,旋轉完成會用到TreeNode pParent = parent.parent;parent.parent = subL;// 修改 subL 的指向if(root == parent){root = subL;root.parent = null;}else{if(pParent.left == parent){pParent.left = subL;}else{pParent.right = subL;}}subL.parent = pParent;// 修改平衡因子subL.bf = 0;parent.bf = 0;}

如果 parent 的平衡因子等于 2,并且 cur 的平衡因子等于 -1,表示 parent子樹的右子樹高度高,cur 子樹的左子樹高度高,此時通過右旋 cur 子樹,降低 cur 左樹的高度,再左旋 parent 子樹,降低 parent 右樹的高度,使樹重新達到平衡;

    private void rotateRL(TreeNode parent){TreeNode subR = parent.right;TreeNode subRL = subR.left;int bf = subRL.bf;rotateRight(subR);rotateLeft(parent);if(bf == -1){parent.bf = 0;subRL.bf = 0;subR.bf = 1;}else if(bf == 1){parent.bf = -1;subRL.bf = 0;subR.bf = 0;}}

如果 parent 的平衡因子等于 -2,并且 cur 的平衡因子等于 1,表示 parent子樹的左子樹高度高,cur 子樹的右子樹高度高,此時通過左旋 cur 子樹,降低 cur 右樹的高度,再右旋 parent 子樹,降低 parent 左樹的高度,使樹重新達到平衡;

    private void rotateLR(TreeNode parent){TreeNode subL = parent.left;TreeNode subLR = subL.right;int bf = subLR.bf;rotateLeft(subL);rotateRight(parent);if(bf == -1){parent.bf = 1;subL.bf = 0;subLR.bf = 0;}else if(bf == 1){subL.bf = -1;subLR.bf = 0;parent.bf = 0;}}

修改平衡因子需要從下往上依次修改,直到 parent 為空;

代碼實現:

    public TreeNode root;public boolean insert(int val){// 1. 插入節點TreeNode node = new TreeNode(val);if(root == null){root = node;return true;}TreeNode parent = null;TreeNode cur = root;while(cur != null){if(cur.val < val){parent = cur;cur = cur.right;}else if(cur.val > val){parent = cur;cur = cur.left;}else{return false;}}// cur == nullif(parent.val < val){parent.right = node;}else{parent.left = node;}node.parent = parent;cur = node;// 2. 平衡因子的修改while(parent != null){if(cur == parent.left){parent.bf--;}else{parent.bf++;}if(parent.bf == 0){return true;}else if(parent.bf == 1 || parent.bf == -1){cur = parent;parent = parent.parent;}else{if(parent.bf == 2){if(cur.bf == 1){// 左單旋rotateLeft(parent);}else{// cur.bf == -1rotateRL(parent);}}else{ // parent.bf == -2if(cur.bf == -1){// 右單旋rotateRight(parent);}else{rotateLR(parent);}}return true;}}return true;}

?4. AVL樹的驗證

1. 驗證其為二叉搜索樹

利用二叉搜索樹的性質:二叉搜索樹的中序遍歷是一個有序數組;

    // 中序遍歷 - 有序表示當前樹是二叉搜索樹public void inOrder(TreeNode root){if(root == null){return;}inOrder(root.left);System.out.print(root.val + " ");inOrder(root.right);}

2. 驗證其為平衡樹

?如果每一棵子樹都是平衡樹,則這棵樹是平衡樹;

    public int getHeight(TreeNode root){if(root == null) return 0;int left = getHeight(root.left);if(left == -1) return -1;int right = getHeight(root.right);if(right == -1) return -1;if(Math.abs(left - right) > 1) return -1;return Math.max(left, right) + 1;}

5. AVL樹的性能分析

AVL樹是一個高度絕對平衡的二叉搜索樹,查詢的時間復雜度為O(longN);

當時AVL樹插入或者刪除節點的時候就會涉及到大量的旋轉,性能比較低;

因此 AVL 樹適用于查詢數據,并且這些數據不會被經常修改;

三、紅黑樹

1. 紅黑樹的性質

  • 1. 每個節點 不是紅色就是黑色;
  • 2. 根節點是黑色的;
  • 3. 如果一個節點是紅色的,則它的兩個孩子節點是黑色的(沒有兩個連續的紅色節點);
  • 4. 對于每個節點,從該節點到其所有后代葉節點的簡單路徑上,均包含相同數目的黑色節點;
  • 5. 每個葉子節點都是黑色的(葉子節點指的是空節點);

2. 紅黑樹的節點定義

left 表示當前節點的左子樹;

right 表示當前節點的右子樹;

parent 表示當前節點的父親節點;?

val 表示當前節點的值;

color 表示當前節點的顏色;

RBTreeNode(int val):表示紅黑樹節點的構造方法;

注意:紅黑樹默認插入節點的顏色是紅色的;

如果插入節點是黑色的,為了滿足紅黑樹不同路徑上具有相同數量黑色節點的性質,那么就需要在所有路徑上都插入一個黑色節點,這些節點是沒有意義的,因此默認節點是紅色;

public class RBTree {static class RBTreeNode{public RBTreeNode left;public RBTreeNode right;public RBTreeNode parent;public int val;public COLOR color;public RBTreeNode(int val){this.val = val;// 節點默認的顏色為紅色,因為如果插入黑色節點,會導致不同路徑上黑色節點的數量不一樣多,// 這樣還需要插入額外的黑色節點,才能保持紅黑樹的性質this.color = COLOR.RED;}}// 紅黑樹的屬性和方法// ......
}

3. 紅黑樹節點的插入

root 表示紅黑樹的根節點;

insert(int val): boolean 在紅黑樹中插入節點;?

思路:

1. 如果樹為空,那么新插入的節點就是樹的根節點,插入后將根節點的顏色置為黑色;

2. 查找

節點的插入方式和二叉搜索樹相同,定義 cur 找要插入節點的位置,parent 指向 cur 的父節點;

如果 cur 的值小于 val,去右子樹找,如果 cur 的值大于 val,去左子樹找找,如果 cur 的值等于 val,說明節點已經存在,不能進行插入,返回 false 即可;?

3. 插入

如果 cur 為空,表示找到了插入位置,如果節點的值小于 parent 的值,插入到 parent 左邊,如果節點的值大于 parent 的值,插入到 parent 的右邊,再讓 cur 重新指向新插入的節點;

4. 調整顏色

插入一個節點,如果此時插入節點的父親節點也是紅色的,那么就不能滿足紅黑樹不能有兩個連續紅色節點的性質,因此為了解決這個問題,就需要對紅黑樹的顏色進行向上調整;

使用 grandFather 指向?parent 節點的父親節點,uncle 指向 grandFather 的另外一個子節點;

如果 parent 是 grandFather 的左子樹,分為以下三種情況處理:

情況 1:parent 為紅色,uncle 指向 grandFather 的右子樹,且顏色為紅色

parent 和 uncle 調整為黑色,grandFather 調整為紅色,如下所示:

調整完成后 cur 指向 grandFather,parent 指向 cur 的父親節點;?

情況 2:parent 為紅色,uncle 為黑色,grandFather 為黑色,cur 為 parent 的左子樹

先右旋 grandFather,完成后 parent 顏色置為黑色,grandFather 顏色置為紅色,如下圖:

情況 3:parent 為紅色,uncle 為黑色,grandFather 為黑色,cur 為 parent 的右子樹
先左旋 parent,再交換 parent 和 cur 指向的位置,得到的情況和情況 2 是相同的,之后再按照情況的處理方式進行處理即可,如下圖:

同理,如果 parent 是 grandFather 的左子樹,也分為以下三種情況處理:

情況 1:parent 為紅色,uncle 指向 grandFather 的左子樹,且顏色為紅色

parent 和 uncle 調整為黑色,grandFather 調整為紅色,如下所示:

調整完成后 cur 指向 grandFather,parent 指向 cur 的父親節點;?

情況 2:parent 為紅色,uncle 為黑色,grandFather 為黑色,cur 為 parent 的右子樹

先左旋 grandFather,完成后 parent 顏色置為黑色,grandFather 顏色置為紅色,如下圖:

情況 3:parent 為紅色,uncle 為黑色,grandFather 為黑色,cur 為 parent 的左子樹
先右旋 parent,再交換 parent 和 cur 指向的位置,得到的情況和情況 2 是相同的,之后再按照情況的處理方式進行處理即可,如下圖:

5. 處理根節點

向上調整顏色完成后,根節點有可能會被調整為紅色,這是要重新把根節點的顏色調整為黑色,返回 true;?

    public RBTreeNode root;public boolean  insert(int val){RBTreeNode node = new RBTreeNode(val);if(this.root == null){this.root = node;this.root.color = COLOR.BLACK;return true;}RBTreeNode cur = root;RBTreeNode parent = null;while(cur != null){if(cur.val < val){parent = cur;cur = cur.right;}else if(cur.val > val){parent = cur;cur = cur.left;}else{return false;}}// cur == null,找到了應該插入的位置if(parent.val < val){parent.right = node;}else{parent.left = node;}node.parent = parent;cur = node;// 修改顏色while(parent != null && parent.color == COLOR.RED){RBTreeNode grandFather = parent.parent;if(grandFather.left == parent){RBTreeNode uncle = grandFather.right;// 情況 1if(uncle != null && uncle.color == COLOR.RED){parent.color = COLOR.BLACK;uncle.color = COLOR.BLACK;grandFather.color = COLOR.RED;cur = grandFather;parent = cur.parent;}else{// parent.color == COLOR.BLANK || uncle.color == COLOR.BLANK// 情況 3:if(parent.right == cur){// 左旋rotateLeft(parent);RBTreeNode tmp = parent;parent = cur;cur = tmp;}// 情況 2 grandFather.color = COLOR.BLANK uncle.color == COLOR.BLANKrotateRight(grandFather);parent.color = COLOR.BLACK;grandFather.color = COLOR.RED;}}else{// grandFather.right = parentRBTreeNode uncle = grandFather.left;// 情況 1:if(uncle != null && uncle.color == COLOR.RED){parent.color = COLOR.BLACK;uncle.color = COLOR.BLACK;grandFather.color = COLOR.RED;cur = grandFather;parent = cur.parent;}else{// parent.color == COLOR.BLANK || uncle.color == COLOR.BLANK// 情況 3:if(parent.left == cur){rotateRight(parent);RBTreeNode tmp = parent;parent = cur;cur = tmp;}// 情況 2:rotateLeft(grandFather);grandFather.color = COLOR.RED;parent.color = COLOR.BLACK;}}}this.root.color = COLOR.BLACK;return true;}

4. 紅黑樹的驗證

驗證紅黑樹分兩步:

第一步,驗證其為二叉搜索樹,采用中序遍歷的方式

    // 第一步:驗證是否為二叉搜索樹public void inOrder(RBTreeNode root){if(root == null) return;inOrder(root.left);System.out.print(root.val + " ");inOrder(root.right);}

第二步,驗證紅黑樹的性質:

  • 根節點為黑色;
  • 沒有連續的紅色節點;
  • 每條路徑上的黑色節點的數量是相同的;?
    public boolean isRBTree(RBTreeNode root, int pathBlackNum, int blackNum){if(root == null) {return true;}// 驗證紅黑樹的性質,分為三個性質進行驗證// 第一步:驗證根節點是否為黑色if(root.color == COLOR.RED){System.out.println("根節點為紅色!");return false;}boolean flag = false;// 第二步:驗證是否存在連續的兩個紅色的節點flag = checkRedNode(root);if(!flag) return false;// 第三步:驗證是否每條路徑上的黑色節點數量都相同flag = checkBlackNodeNum(root, pathBlackNum, blackNum);if(!flag) return false;return true;}private boolean checkRedNode(RBTreeNode root){if(root == null){return true;}// 遍歷二叉樹,如果遇到紅色的節點,看一下它的父節點是否為紅色即可if(root.color == COLOR.RED){RBTreeNode parent = root.parent;if(parent.color == COLOR.RED){System.out.println("連續兩個紅色的節點!");return false;}}return checkRedNode(root.left) && checkRedNode(root.right);}private boolean checkBlackNodeNum(RBTreeNode root, int pathBlackNum, int blackNum) {if(root == null){if(pathBlackNum == blackNum){return true;}System.out.println("路徑上的黑色節點數量不相同!");return false;}if(root.color == COLOR.BLACK){pathBlackNum++;}return checkBlackNodeNum(root.left, pathBlackNum, blackNum) &&checkBlackNodeNum(root.right, pathBlackNum, blackNum);}

四、AVL樹和紅黑樹的比較

?AVL樹和紅黑樹都是二叉搜索樹,也都是二叉平衡樹;

AVL樹追求絕對的高度平衡,即左右子樹的高度差不超過 1;

紅黑樹不追求絕對平衡,保證每條路徑上的黑色節點的數量相同即可且沒有連續的紅色節點,即最長路徑上的長度是最短路徑長度的二倍;

AVL樹在插入和刪除節點的時候,需要大量的旋轉,不適合進行頻繁的插入和刪除;

紅黑樹在插入和刪除節點的時候,減少了旋轉的次數,因此在實際應用中更多;

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

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

相關文章

Maven引入第三方JAR包實戰指南

要將第三方提供的 JAR 包引入本地 Maven 倉庫&#xff0c;可通過以下步驟實現&#xff08;以 Oracle JDBC 驅動為例&#xff09;&#xff1a;&#x1f527; 方法 1&#xff1a;使用 install:install-file 命令&#xff08;推薦&#xff09;定位 JAR 文件 將第三方 JAR 包&#…

JavaSE -- 泛型詳細介紹

泛型 簡介 集合存儲數據底層是利用 Object 來接收的&#xff0c;意思是說如果不對類型加以限制&#xff0c;所有數據類型柔和在一起&#xff0c;這時如何保證數據的安全性呢&#xff08;如果不限制存入的數據類型&#xff0c;任何數據都能存入&#xff0c;當我們取出數據進行強…

使用 Python 實現 ETL 流程:從文本文件提取到數據處理的全面指南

文章大綱&#xff1a; 引言&#xff1a;什么是 ETL 以及其重要性 ETL&#xff08;提取-轉換-加載&#xff09;是數據處理領域中的核心概念&#xff0c;代表了從源數據到目標系統的三個關鍵步驟&#xff1a;**提取&#xff08;Extract&#xff09;**數據、**轉換&#xff08;Tra…

selenium基礎知識 和 模擬登錄selenium版本

前言 selenium框架是Python用于控制瀏覽器的技術,在Python爬蟲獲取頁面源代碼的時候,是最重要的技術之一,通過控制瀏覽器,更加靈活便捷的獲取瀏覽器中網頁的源代碼。 還沒有安裝啟動selenium的同志請先看我的上一篇文章進行配置啟動 和 XPath基礎 對selenium進行瀏覽器和驅動…

JS 網頁全自動翻譯v3.17發布,全面接入 GiteeAI 大模型翻譯及自動部署

兩行 js 實現 html 全自動翻譯。 無需改動頁面、無語言配置文件、無 API Key、對 SEO 友好&#xff01; 升級說明 translate.service 深度綁定 GiteeAI 作為公有云翻譯大模型算力支持translate.service 增加shell一鍵部署后通過訪問自助完成GiteeAI的開通及整個接入流程。增加…

數據結構:數組:插入操作(Insert)與刪除操作(Delete)

目錄 插入操作&#xff08;Inserting in an Array&#xff09; 在紙上模擬你會怎么做&#xff1f; 代碼實現 復雜度分析 刪除操作&#xff08;Deleting from an Array&#xff09; 在紙上模擬一下怎么做&#xff1f; 代碼實現 復雜度分析 插入操作&#xff08;Inserti…

Qt之修改純色圖片的顏色

這里以修改QMenu圖標顏色為例,效果如下: MyMenu.h #ifndef MYMENU_H #define MYMENU_H#include <QMenu>class MyMenu : public QMenu { public:explicit MyMenu(QWidget *parent = nullptr);protected:void mouseMoveEvent(QMouseEvent *event) override; };#endif /…

uni-app實現單選,多選也能搜索,勾選,選擇,回顯

前往插件市場安裝插件下拉搜索選擇框 - DCloud 插件市場&#xff0c;該插件示例代碼有vue2和vue3代碼 是支持微信小程序和app的 示例代碼&#xff1a; <template><view><!-- 基礎用法 --><cuihai-select-search:options"options"v-model&quo…

【機器學習深度學習】 微調的十種形式全解析

目錄 一、為什么要微調&#xff1f; 二、微調的 10 種主流方式 ? 1. 全參數微調&#xff08;Full Fine-tuning&#xff09; ? 2. 凍結部分層微調&#xff08;Partial Fine-tuning&#xff09; ? 3. 參數高效微調&#xff08;PEFT&#xff09; &#x1f538; 3.1 LoRA&…

信刻光盤安全隔離與文件單向導入/導出系統

北京英特信網絡科技有限公司成立于2005年&#xff0c;是專業的數據光盤擺渡、刻錄分發及光盤存儲備份領域的科技企業&#xff0c;專注為軍隊、軍工、司法、保密等行業提供數據光盤安全擺渡、跨網交換、檔案歸檔檢測等專業解決方案。 公司立足信創產業&#xff0c;產品國產安全可…

Python-標準庫-os

1 需求 2 接口 3 示例 4 參考資料 在 Python 中&#xff0c;os&#xff08;Operating System&#xff09;模塊是一個非常重要的內置標準庫&#xff0c;提供了許多與操作系統進行交互的函數和方法&#xff0c;允許開發者在 Python 程序中執行常見的操作系統任務&#xff0c;像文…

OpenCV CUDA模塊設備層-----在 GPU 上執行類似于 std::copy 的操作函數warpCopy()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 OpenCV 的 CUDA 模塊&#xff08;cudev&#xff09; 中的一個設備端內聯模板函數&#xff0c;用于在 GPU 上執行類似于 std::copy 的操作&#xff…

Vue Router 中$route.path與 params 的關系

1. params 參數的本質&#xff1a;路徑的動態片段在 Vue Router 中&#xff0c;params 參數是通過路由配置的動態路徑片段定義的&#xff0c;例如&#xff1a;// 路由配置{ path: /user/:id, component: User }當訪問/user/123時&#xff0c;/user/123是完整的路徑&#xff0c;…

React 極簡響應式滑塊驗證組件實現,隨機滑塊位置

&#x1f3af; 滑塊驗證組件 (Slider Captcha) 一個現代化、響應式的滑塊驗證組件&#xff0c;專為 React 應用設計&#xff0c;提供流暢的用戶體驗和強大的安全驗證功能。 ? 功能特性 &#x1f3ae; 核心功能 智能滑塊拖拽 – 支持鼠標和觸摸屏操作&#xff0c;響應靈敏隨…

STM32第十六天藍牙模塊

一&#xff1a;藍牙模塊HC-05 1&#xff1a;硬件引腳配置&#xff1a; | 標號 | PIN | 說明 | |------|-------|---------------------------------------| | 1 | START | 狀態引出引腳&#xff08;未連接/連接輸出信號時&#xff09; |…

時序數據庫IoTDB用戶自定義函數(UDF)使用指南

1. 編寫UDF時序數據庫IoTDB為用戶提供了編寫UDF的JAVA API&#xff0c;用戶可以自主實現UDTF&#xff08;用戶自定義轉換函數&#xff09;類&#xff0c;IoTDB將通過類加載機制裝載用戶編寫的類。Maven依賴如果使用Maven&#xff0c;可以從Maven庫中搜索以下依賴&#xff0c;并…

Linux國產與國外進度對壘

Linux國產與國外進度對壘 引言國產Linux的發展現狀國外Linux的發展現狀技術對比國產Linux的挑戰與機遇國外Linux的優勢與局限結論 引言 簡述Linux在全球操作系統市場中的地位國產Linux的發展背景與意義國外主流Linux發行版的現狀 國產Linux的發展現狀 主要國產Linux發行版介…

Jenkins-Email Extension 插件插件

Editable Email Notification Editable Email Notification 是 Jenkins 的 Email Extension 插件的核心功能&#xff0c;用于自定義郵件通知&#xff0c;包括郵件主題、內容、收件人、發件人等 屬性 1.Project From 項目發件人&#xff0c;設置郵件的發件人地址 **注意&…

windows系統下將Docker Desktop安裝到除了C盤的其它盤中

windows系統下安裝docker會自動安裝到C盤&#xff0c;可以采用下面的方法將其安裝到其它盤中1、先下載Docker Desktop安裝程序Docker Desktop Installer.exe&#xff0c;比如你下載到了C:\Users\YourUsername\Downloads 文件夾中。 2、打開 PowerShell 進入C:\Users\YourUser…

視頻工具箱 1.1.1 |小而美的視頻處理工具,支持多種常用功能

VideoTools是一款基于FFmpeg的小而美的視頻處理工具&#xff0c;專為需要快速高效地進行視頻編輯的用戶設計。這款工具無需安裝&#xff0c;體積僅約200KB&#xff0c;提供了視頻壓縮、格式轉換、轉GIF、修改分辨率、加速播放以及音頻提取等多種常用功能。其用戶界面簡潔直觀&a…