數據結構之樹結構(下)

各種各樣的大樹

平衡二叉樹 (AVL樹)

普通二叉樹存在的問題

  1. 左子樹全部為空,從形式上看,更像一個單鏈表

  2. 插入速度沒有影響

  3. 查詢速度明顯降低(因為需要依次比較),不能發揮BST的優勢,因為每次還需要比較左子樹,其查詢速度比單鏈表還慢

  4. 解決方案-平衡二叉樹(AVL)

基本介紹

  • 平衡二叉樹也叫平衡二叉搜索樹(Self-balancing binary search tree)又被稱為AVL樹,可以保證查詢效率較高。
  • 具有以下特點:它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1
    并且左右兩個子樹都是一棵平衡二叉樹。平衡二叉樹的常用實現方法有紅黑樹、
    AVL、替罪羊樹、Treap、伸展樹等,

應用案例

判斷樹的高度

// 返回左子樹的高度
public int leftHeight() {if (left == null) {return 0;}return left.height();
}// 返回右子樹的高度
public int rightHeight() {if (right == null) {return 0;}return right.height();
}// 返回當前結點的高度,以該結點為根結點的樹的高度
public int height() {return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height()) + 1;
}
單旋轉(左旋轉)

左旋轉步驟

  • 前提條件: r i g h t H e i g h t ( ) ? l e f t H e i g h t ( ) > 1 rightHeight() - leftHeight() > 1 rightHeight()?leftHeight()>1
  1. 創建一個新的節點newNode(以root 這個值創建),創建一個新的節點,值等于當前根節點的值,把新節點的左子樹設置了當前節點的左子樹
    // newNode.left = left
  2. 把新節點的右子樹設置為當前節點的右子樹的左子樹
    // newNode.right =right.left;
  3. 把當前節點的值換為右子節點的值
    // value=right.value;
  4. 把當前節點的右子樹設置成當前結點的右子樹的右子樹
    // right=right.right;
  5. 把當前節點的左子樹設置為新節點
    // left=newLeft;
// 左旋轉
private void leftRotate() {// 1. 創建一個新的節點newNode(以root 這個值創建)// 創建一個新的節點,值等于當前根節點的值,把新節點的左子樹設置了當前節點的左子樹Node newNode = new Node(value);newNode.left = left;// 2.把新節點的右子樹設置為當前節點的右子樹的左子樹newNode.right = right.left;// 3.把當前節點的值換為右子節點的值value = right.value;// 4.把當前節點的右子樹設置成當前結點的右子樹的右子樹right = right.right;// 5.把當前節點的左子樹設置為新節點left = newNode;
}

單旋轉(右旋轉)

步驟

  1. 創建一個新的節點newNode(以root 這個值創建),創健一個新的節點,值等于當前根節點的值
  2. 把新節點的右子樹設置了當前節點的右子樹
    // newNode.right right
  3. 把新節點的左子樹設置為當前節點的左子樹的右子樹
    // newNode.left =left.right;
  4. 把當前節點的值換為左子節點的值
    // value=left.value;
  5. 把當前節點的左子樹設置成左子樹的左子樹
    // left=left.left;
  6. 把當前節點的右子樹設置為新節點
    // right=newLeft;
// 右旋轉
public void rightRotate() {// 1.創建一個新的節點newNode(以root 這個值創建)// 創健一個新的節點,值等于當前根節點的值Node newNode = new Node(value);// 2.把新節點的右子樹設置了當前節點的右子樹newNode.right = right;// 3.把新節點的左子樹設置為當前節點的左子樹的右子樹newNode.left = left.right;// 4.把當前節點的值換為左子節點的值value = left.value;// 5.把當前節點的左子樹設置成左子樹的左子樹left = left.left;// 6.把當前節點的右子樹設置為新節點right = newNode;
}

雙旋轉

在單旋轉中 (即一次旋轉) 就可以將非平衡二叉樹轉成平衡二叉樹,但是在某些情況下,單旋轉不能完成平衡二叉樹的轉換

情況1??

在這里插入圖片描述

實現步驟

  1. 當右旋轉的條件時

    • 如果它的左子樹的右子樹高度大于它的左子樹的右子樹的高度
    • 先對當前這個結點的左節點進行左旋轉
    • 再對當前結點進行右旋轉
  2. 當左旋轉時

    • 如果它的右子樹的左子樹高度大于它的右子樹的右子樹的高度
    • 先對當前這個結點的右結點進行右旋轉
    • 再對當前結點進行左旋轉
/*** 添加在Node類的添加結點的方法里邊* 每添加一個結點就判斷一次
*/
// 單旋轉
// 當添加完一個結點后,如果:(右子樹的高度-左子樹的高度) > 1,左旋轉
if (rightHeight() - leftHeight() > 1) {// 如果它的右子樹的左子樹高度大于它的右子樹的右子樹的高度if (right != null && right.rightHeight() > right.leftHeight()) {// 先對當前這個結點的右結點進行右旋轉rightRotate();}leftRotate();  // 左旋轉return; // 一定要返回,否則會出現其他問題,提高VM處理速度
}
// 當添加完一個結點后,如果:(左子樹的高度-右子樹的高度) > 1,右旋轉
if (leftHeight() - rightHeight() > 1) {// 如果它的左子樹的右子樹高度大于它的左子樹的右子樹的高度if (left != null && left.rightHeight() > left.leftHeight()) {// 先對當前這個結點的左節點進行左旋轉left.leftRotate();}rightRotate();  // 右旋轉
}

總代碼
package com.xiaolu.avl;/*** @author 林小鹿* @version 1.0*/
public class AvlTreeDemo {public static void main(String[] args) {
//        int[] arr = {4, 3, 6, 5, 7, 8};
//        int[] arr = {10, 12, 8, 9, 7, 6};int[] arr = {10, 11, 7, 6, 8, 9};AVLTree avlTree = new AVLTree();// 添加結點for (int i = 0; i < arr.length; i++) {avlTree.add(new Node(arr[i]));}// 中序遍歷avlTree.infixOrder();System.out.println("平衡處理 (左旋轉)~~~");System.out.println("樹的高度:" + avlTree.getRoot().height()); // 4System.out.println("樹的左子樹高度:" + avlTree.getRoot().leftHeight()); // 1System.out.println("樹的右子樹高度:" + avlTree.getRoot().rightHeight()); // 3System.out.println("當前根結點 = " + avlTree.getRoot());}
}// 創建AVLTree
class AVLTree {private Node root;public Node getRoot() {return root;}// 查找要刪除的結點public Node search(int value) {if (root == null) {return null;} else {return root.search(value);}}// 查找要刪除的父結點public Node searchParent(int value) {if (root == null) {return null;} else {return root.searchParent(value);}}/*** 刪除node 為根結點的二叉排序樹的最小結點的值的同時返回以node 為根結點的二叉排序樹的最小結點** @param node 傳入的結點 (當做二叉排序樹的根結點)* @return 返回以node 為根結點的二叉排序樹的最小結點的值*/public int delRightTreeMin(Node node) {Node target = node;// 循環的查找左結點,就會找到最小值while (target.left != null) {target = target.left;}// 這是target就指向了最小結點// 刪除最小結點delNode(target.value);return target.value;}// 刪除結點public void delNode(int value) {if (root == null) {return;} else {// 找到需要刪除的結點 targetNodeNode targetNode = search(value);// 如果沒有找到要刪除的結點if (targetNode == null) {return;}// 如果這顆二叉排序樹只有一個結點 (即本身就是父節點)if (root.left == null && root.right == null) {root = null;return;}// 查詢父節點Node parent = searchParent(value);// 如果待刪除的結點是葉子結點if (targetNode.left == null && targetNode.right == null) {// 刪除葉子結點// 判斷 targetNode 是父節點的左子結點還是右子節點if (parent.left != null && parent.left.value == value) {parent.left = null;} else if (parent.right != null && parent.right.value == value) {parent.right = null;}} else if (targetNode.left != null && targetNode.right != null) {// 刪除有兩顆子樹的結點int minVal = delRightTreeMin(targetNode.right);targetNode.value = minVal;} else {// 刪除只有一顆子樹的結點// 如果要刪除的結點有左子結點if (targetNode.left != null) {if (parent != null) {// 如果targetNode 是parent 的左子結點if (parent.left.value == value) {parent.left = targetNode.left;} else {// 如果targetNode 是parent 的右子結點parent.right = targetNode.left;}} else {root = targetNode.left;}} else {if (parent != null) {// 如果要刪除的結點有右子結點if (parent.left.value == value) {// 如果targetNode 是parent 的左子結點parent.left = targetNode.right;} else {// 如果targetNode 是parent 的右子結點parent.right = targetNode.right;}} else {root = targetNode.right;}}}}}// 添加結點public void add(Node node) {if (root == null) {// 如果root為空則直接讓root指向noderoot = node;} else {root.add(node);}}// 中序遍歷public void infixOrder() {if (root == null) {System.out.println("二叉樹為空,無法遍歷");} else {root.infixOrder();}}
}// 創建Node結點
class Node {int value;Node left;Node right;public Node(int value) {this.value = value;}// 返回左子樹的高度public int leftHeight() {if (left == null) {return 0;}return left.height();}// 返回右子樹的高度public int rightHeight() {if (right == null) {return 0;}return right.height();}// 返回當前結點的高度,以該結點為根結點的樹的高度public int height() {return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height()) + 1;}// 左旋轉private void leftRotate() {// 1. 創建一個新的節點newNode(以root 這個值創建)// 創建一個新的節點,值等于當前根節點的值,把新節點的左子樹設置了當前節點的左子樹Node newNode = new Node(value);newNode.left = left;// 2.把新節點的右子樹設置為當前節點的右子樹的左子樹newNode.right = right.left;// 3.把當前節點的值換為右子節點的值value = right.value;// 4.把當前節點的右子樹設置成當前結點的右子樹的右子樹right = right.right;// 5.把當前節點的左子樹設置為新節點left = newNode;}// 右旋轉public void rightRotate() {// 1.創建一個新的節點newNode(以root 這個值創建)// 創健一個新的節點,值等于當前根節點的值Node newNode = new Node(value);// 2.把新節點的右子樹設置了當前節點的右子樹newNode.right = right;// 3.把新節點的左子樹設置為當前節點的左子樹的右子樹newNode.left = left.right;// 4.把當前節點的值換為左子節點的值value = left.value;// 5.把當前節點的左子樹設置成左子樹的左子樹left = left.left;// 6.把當前節點的右子樹設置為新節點right = newNode;}/*** 查找要刪除的結點** @param value 待刪除的結點的值* @return 如果找到則返回該結點,否則返回空*/public Node search(int value) {if (value == this.value) {return this;} else if (value < this.value) {// 如果查找的值小于當前結點,就向左子樹遞歸查找if (this.left == null) {// 如果左子樹為空return null;}return this.left.search(value);} else {// 如果查找的值不小于當前結點,向右子樹遞歸查找if (this.right == null) {// 如果右子樹為空return null;}return this.right.search(value);}}/*** 查找要刪除結點的父結點** @param value 要找到的結點的值* @return 返回的是要刪除的結點的父結點,如果沒有就返回null*/public Node searchParent(int value) {// 如果當前結點就是要刪除的結點的父節點,就返回if ((this.left != null && this.left.value == value)|| (this.right != null && this.right.value == value)) {return this;} else {// 如果查找的值小于或大于當前結點的值,并且當前結點的左子節點不為空if (value < this.value && this.left != null) {return this.left.searchParent(value); // 向左子樹遞歸查找} else if (value > this.value && this.right != null) {return this.right.searchParent(value); // 向右子樹遞歸查找} else {return null; // 沒有找到父節點}}}// 按二叉排序樹的形式遞歸添加結點public void add(Node node) {if (node == null) {return;}// 判斷傳入的結點的值與當前子樹的根結點的值關系if (node.value < this.value) {if (this.left == null) {this.left = node;} else {// 遞歸得向左子樹添加 nodethis.left.add(node);}} else { // 添加的結點的值大于當前結點的值if (this.right == null) {this.right = node;} else {// 遞歸得向右子樹添加 nodethis.right.add(node);}}// 單旋轉// 當添加完一個結點后,如果:(右子樹的高度-左子樹的高度) > 1,左旋轉if (rightHeight() - leftHeight() > 1) {// 如果它的右子樹的左子樹高度大于它的右子樹的右子樹的高度if (right != null && right.leftHeight() > right.rightHeight()) {// 先對當前這個結點的右結點進行右旋轉rightRotate();}leftRotate();  // 左旋轉return; // 一定要返回,否則會出現其他問題,提高VM處理速度}// 當添加完一個結點后,如果:(左子樹的高度-右子樹的高度) > 1,右旋轉if (leftHeight() - rightHeight() > 1) {// 如果它的左子樹的右子樹高度大于它的左子樹的右子樹的高度if (left != null && left.rightHeight() > left.leftHeight()) {// 先對當前這個結點的左節點進行左旋轉left.leftRotate();}rightRotate();  // 右旋轉}}// 中序遍歷public void infixOrder() {if (this.left != null) {this.left.infixOrder();}System.out.println(this);if (this.right != null) {this.right.infixOrder();}}@Overridepublic String toString() {return "Node[" +"value=" + value +']';}
}

多路查找樹

在這里插入圖片描述

二叉樹存在的問題

  • 二叉樹需要加載到內存的,如果二叉樹的節點少,沒有什么問題,但是如果二叉樹的節點很多(比如1億),就存在如下問題

  • 問題1:在構建二叉樹時,需要多次進行 I / O I/O I/O 操作海量數據存在數據庫或文件中),節點海量,構建二叉樹時,速度有影響

  • 問題2:節點海量,也會造成二叉樹的高度很大,會降低操作速度

多叉樹

在二叉樹中,每個節點有數據項,最多有兩個子節點,如果允許每個節點可以有更多的數據項和更多的子節點,就是多叉樹(multiway tree)

多叉樹通過重新組織節點,減少樹的高度,能對二叉樹進行優化

2-3樹

2-3樹是最簡單的B-樹結構,其他像2-3-4樹同理

特點

  • 2-3樹的所有葉子節點都在同一層.(只要是B樹都滿足這個條件)
  • 有兩個子節點的節點叫二節點,二節點要么沒有子節點,要么有兩個子節點
  • 有三個子節點的節點叫三節點,三節點要么沒有子節點,要么有三個子節點.
  • 2-3樹是由二節點和三節點構成的樹。

插入規則:

1)2-3樹的所有葉子節點都在同一層.(只要是B樹都滿足這個條件)
2)有兩個子節點的節點叫二節點,二節點要么沒有子節點,要么有兩個子節點

3)有三個子節點的節點叫三節點,三節點要么沒有子節點,要么有三個子節點
4)當按照規則插入一個數到某個節點時,不能滿足上面三個要求,就需要拆,先向上拆,如果上層滿,則拆本層,拆后仍然需要滿足上面3個條件。
5)對于三節點的子樹的值大小仍然遵守(BST 二叉排序樹)的規則


B樹

B-tree,B即Balanced

基本介紹

  • B樹的階:節點的最多子節點個數。比如2-3樹的階是3,2-3-4樹的階是4
  • B樹的搜索,從根結點開始,對結點內的關鍵字(有序)序列進行二分查找,如果命中側結束,否測進入查詢關鍵字所屬范圍的兒子結點;重復,直到所對應的兒子指針為空,或已經是葉子結點
  • 關鍵字集合分布在整顆樹中,即葉子節點和非葉子節點都存放數據
  • 搜索有可能在非葉子結點結束
  • 其搜索性能等價于在關鍵字全集內做一次二分查找

在這里插入圖片描述


B+樹

B+樹是B樹的變體,也是一種多路搜索樹

基本介紹

  • B+樹的搜索與B樹也基本相同,區別是B+樹只有達到葉子結點才命中(B樹可以在非葉子結點命中),其性能也等價于在關鍵字全集做一次二分查找
  • 所有關鍵字都出現在葉子結點的鏈表中(即數據只能在葉子節點【也叫稠密索引】),且鏈表中的關鍵字數據恰好是有序的。
  • 不可能在非葉子結點命中
  • 非葉子結點相當于是葉子結點的索引(稀疏索引)葉子結點相當于是存儲(關鍵字)數據的數據層
  • 更適合文件索引系統
  • B樹和B+時各有自己的應用場景,不能說B+完全比B樹好,反之亦然

在這里插入圖片描述


B*樹

B*樹是B+樹的變體,在B+樹的非根和非葉子結點再增加指向兄弟的指正

基本說明

  • B*樹定義了非葉子結點關鍵字個數至少為(2/3)*M,即塊的最低使用率為2/3,而B+樹的塊的最低使用率為B+樹的1/2。
  • 從第1個特點我們可以看出,B*樹分配新結點的概率比B+樹要低,空間使用率更高

在這里插入圖片描述

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

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

相關文章

javaWeb個人學習04

AOP核心概念: 連接點: JoinPoint, 可以被AOP控制的方法 通知: Advice 指哪些重復的邏輯&#xff0c;也就是共性功能(最終體現為一個方法) 切入點: PointCut, 匹配連接點的條件&#xff0c;通知僅會在切入點方法執行時被應用 目標對象: Target, 通知所應用的對象 通知類…

docker基線安全修復和容器逃逸修復

一、docker安全基線存在的問題和修復建議 1、將容器的根文件系統掛載為只讀 修復建議&#xff1a; 添加“ --read-only”標志&#xff0c;以允許將容器的根文件系統掛載為只讀。 可以將其與卷結合使用&#xff0c;以強制容器的過程僅寫入要保留的位置。 可以使用命令&#x…

航拍無人機技術,航拍無人機方案詳解,無人機攝影技術

航拍無人機是利用遙控技術和攝像設備&#xff0c;在空中進行拍攝和錄像的無人機。這種無人機通常具有高清攝像設備、圖像傳輸設備、GPS定位系統、智能控制系統等&#xff0c;可以輕松實現各種拍攝角度和高度&#xff0c;廣泛應用于影視制作、旅游景區航拍、城市規劃、環保監測等…

【數據結構與算法】回溯法解題20240301

這里寫目錄標題 一、78. 子集1、nums [1,2,3]為例把求子集抽象為樹型結構2、回溯三部曲 二、90. 子集 II1、本題搜索的過程抽象成樹形結構如下&#xff1a; 三、39. 組合總和1、回溯三部曲2、剪枝優化 四、LCR 082. 組合總和 II1、思路2、樹形結構如圖所示&#xff1a;3、回溯…

用vivado創建一個賽靈思AXI的IP核

一、新建一個管理IP的任務 二、設置板子&#xff0c;verilog語言和文件位置 三、創建新的IP核 添加一個axi-full的master接口和axi-full的slave接口 四、查看賽靈思AXI代碼 第一個是axi的master接口代碼&#xff0c;下面的是axi的slave接口代碼 五、打包IP核以供后續使用 六、…

共享旅游卡:打開0費用旅游新紀元,探索40+精彩線路

隨著現代生活節奏的加快&#xff0c;旅游成為了許多人釋放壓力、尋求樂趣的方式。然而&#xff0c;面對琳瑯滿目的旅游線路和不斷上漲的旅游費用&#xff0c;許多人望而卻步。 今天&#xff0c;我們要為您介紹一種顛覆傳統旅游方式的創新產品——共享旅游卡。它不僅能讓您以0費…

什么是雙線服務器?

雙線服務器是一種有著兩條高速網絡線路的主機服務器&#xff0c;通常又被稱為雙線獨享服務器&#xff0c;雙線服務器的出現提高了服務器的可靠性&#xff0c;因為雙線服務器對數據與請求可以使用兩條高速網絡線路進行處理&#xff0c;對比于單線服務器&#xff0c;提高了服務器…

easyexcel字體加粗

public static void main(String[] args) { List dataList new ArrayList<>(); dataList.add(new Data(“Data 1”)); dataList.add(new Data(“Data 2”)); dataList.add(new Data(“Data 3”)); // 設置加粗字體WriteCellStyle boldCellStyle new WriteCellStyle();W…

出現 ‘vue‘ 不是內部或外部命令,也不是可運行的程序 或批處理文件的解決方法(圖文界面)

目錄 前言1. 問題所示2. 原理分析3. 解決方法前言 由于Java轉全棧,對此前端的細節點都比他人更加注意,所以此處記錄更有用的信息!(小白都能看懂) 1. 問題所示 出現如下問題: F:\vue_project>vue -version vue 不是內部或外部命令,也不是可運行的程序 或批處理文件…

基于Python的電商評論數據采集與分析|電商API接口數據采集

引言 在電商競爭日益激烈的情況下&#xff0c;商家既要提高產品質量&#xff0c;又要洞悉客戶的想法和需求&#xff0c;關注客戶購買商品后的評論&#xff0c;而第三方商家獲取商品評價主要依賴于人工收集&#xff0c;不但效率低&#xff0c;而且準確度得不到保障。通過使用Py…

鴻蒙 渲染控制

前提&#xff1a;基于官網3.1/4.0文檔。參考官網文檔 基于Android開發體系來進行比較和思考。&#xff08;或有偏頗&#xff0c;自行斟酌&#xff09; 1.概念 ArkUI通過自定義組件的build()函數和builder裝飾器中的聲明式UI描述語句構建相應的UI。在聲明式描述語句中開發者除了…

Ps:繪畫對稱功能

Photoshop 中的繪畫對稱 Paint Symmetry功能允許用戶在畫布上創建對稱的繪畫和設計&#xff0c;極大地提高了創作的效率和準確性&#xff0c;尤其適合于制作復雜的對稱圖形和圖案。 可在使用畫筆工具、鉛筆工具或橡皮擦工具時啟用“繪畫對稱"功能。 提示&#xff1a; 繪畫…

Ubuntu Qt控制終端運行ros

文章目錄 gnome-terminalQt 通過QProcess類Qt 通過system gnome-terminal 在Ubuntu中可以使用man gnome-terminal命令查看gnome-terminal的使用指南&#xff0c;也可在ubuntu manuals查看&#xff1a; NAMEgnome-terminal — 一個終端仿真應用.概要gnome-terminal [-e, --c…

Cocos游戲開發中的金幣落袋效果

引言 Cocos游戲開發中的金幣落袋效果 大家好,不知道大家有沒有被游戲中的一些小細節打動或吸引。 往往游戲就是通過一些與眾不同的細節,去留住玩家。 金幣落袋效果正是如此,它比普通的數值變化來得更加形象,給予玩家成就感和滿足感。 本文重點給大家介紹一下如何在Coc…

深入探索Java集合框架

在Java編程中&#xff0c;數據的組織和存儲是核心部分。為了更有效地管理和操作這些數據&#xff0c;Java提供了一個強大且靈活的集合框架&#xff08;Java Collection Framework&#xff0c;JCF&#xff09;。這個框架不僅簡化了數據結構的處理&#xff0c;還提供了高效的性能…

Opencv基本操作 (上)

目錄 圖像基本操作 閾值與平滑處理 圖像閾值 圖像平滑處理 圖像形態學操作 圖像梯度計算 Sobel 算子 Canny 邊緣檢測 圖像金字塔與輪廓檢測 圖像輪廓 接口定義 輪廓繪制 輪廓特征與相似 模板匹配 傅里葉變換 傅里葉變換的作用 濾波 圖像基本操作 讀取圖像&…

GDPU 算法分析與設計 天碼行空 1

實驗1 排序算法的效率分析 一、【實驗目的】 &#xff08;1&#xff09;復習排序算法的實現過程&#xff1b; &#xff08;2&#xff09;設計平均與最壞情況下時間復雜度的數據環境并理解相關含義&#xff1b; &#xff08;3&#xff09;初步了解算法時間復雜度的分析方法。…

【Maven】Maven 基礎教程(二):Maven 的使用

《Maven 基礎教程》系列&#xff0c;包含以下 2 篇文章&#xff1a; Maven 基礎教程&#xff08;一&#xff09;&#xff1a;基礎介紹、開發環境配置Maven 基礎教程&#xff08;二&#xff09;&#xff1a;Maven 的使用 &#x1f60a; 如果您覺得這篇文章有用 ?? 的話&#…

Qt中關于信號與槽函數的思考

信號與槽函數的思考 以pushbutton控件為例&#xff0c;在主界面上放置一個pushbutton控件&#xff0c;點擊右鍵選擇關聯槽函數&#xff0c;關聯一個click函數&#xff0c;如下圖所示&#xff1a; 在該函數中&#xff0c;實現了一個點擊pushbutton按鈕后&#xff0c;彈出一個窗…

nginx使用詳解--反向代理

什么是反向代理&#xff1f; 正向代理&#xff1a; 一般的訪問流程是客戶端直接向目標服務器發送請求并獲取內容&#xff0c;使用正向代理后&#xff0c;客戶端改為向代理服務器發送請求&#xff0c;并指定目標服務器&#xff08;原始服務器&#xff09;&#xff0c;然后由代理…