探索數據結構:堆的具體實現與應用

?? 歡迎大家來到貝蒂大講堂??

🎈🎈養成好習慣,先贊后看哦~🎈🎈

所屬專欄:數據結構與算法
貝蒂的主頁:Betty’s blog

1. 堆的概念

堆(Heap)是計算機科學中一類特殊的數據結構。堆通常是一個可以被看作一棵完全二樹的數組對象,若滿足:

  • 任意節點的值>=其子節點的值。則稱為大根堆
  • 任意節點的值<=其子節點的值。則稱為小根堆

img

img

2. 堆的實現方式

雖然堆是一種特殊的二叉樹,它既可以用數組存儲也可以用鏈式存儲。但是考慮到其完全二叉樹的特性,我們最好采用數組存儲的方式,因為這樣既方便訪問,也并不會浪費格外的空間。

img

假設某個合法下標為i:

  • 若雙親節點存在,下標為(i-1)/2。
  • 若孩子節點存在,左孩子下標為2i+1,右孩子為2i+2。

3. 堆的功能

  1. 堆的初始化。
  2. 堆的插入。
  3. 堆的刪除。
  4. 獲取堆頂的元素。
  5. 堆的元素個數。
  6. 堆的判空。
  7. 輸出堆。
  8. 建堆。
  9. 銷毀堆。

4. 堆的聲明

因為我用數組實現堆,所以堆的聲明與順序表類似。

typedef int HpDataType;
typedef struct Heap 
{HpDataType* a;//存儲數據int size;//大小int capacity;//容量
}Heap;

5. 堆的實現

5.1. 堆的初始化

5.1.1. 代碼實現
void HeapInit(Heap* hp)//堆的初始化
{assert(hp);hp->a = NULL;hp->size = hp->capacity = 0;
}
5.1.2. 復雜度分析
  • 時間復雜度:沒有額外的時間消耗,時間復雜度為O(1)。
  • 空間復雜度:沒有額外的空間消耗,空間復雜度為O(1)。

5.2. 堆的插入

當我們堆進行插入時可能會破壞堆的原有結構,這時就需要我們對其進行向上調整。

img

5.2.1. 代碼實現
void AdjustUp(Heap* hp, int child)//向上調整
{int parent = (child - 1) / 2;while (child > 0){if (hp->a[child] > hp->a[parent]){swap(&hp->a[child], &hp->a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}
void HeapPush(Heap* hp, HpDataType x)//堆的插入
{assert(hp);if (hp->size == hp->capacity){int newCapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;HpDataType* tmp = (HpDataType*)realloc(hp->a, newCapacity * sizeof(HpDataType));if (tmp == NULL){perror("realloc fail");exit(-1);}hp->a = tmp;hp->capacity = newCapacity;}hp->a[hp->size] = x;hp->size++;AdjustUp(hp, hp->size - 1);//向上調整
}
5.2.2. 復雜度分析
  • 時間復雜度:假設有N個節點,高度為h,2h -1=N。至少調整log2(N+1)-1次,所以時間復雜度為logN。
  • 空間復雜度:沒有開辟額外的空間,空間復雜度為O(1)。

5.3. 堆的刪除

堆的刪除是指刪除堆頂的數據,如果我們刪除堆頂元素并往前覆蓋就可能打亂原有的親緣關系。所以我們可以先將堆頂的元素與末尾元素交換,然后再進行向下調整·。

img

5.3.1. 代碼實現
void swap(HpDataType* x1, HpDataType* x2)
{HpDataType tmp = *x1;*x1 = *x2;*x2 = tmp;
}
void 
void AdjustDown(int* a, int n, int parent)//向下調整
{int child = parent * 2 + 1;//默認左孩子更大while (child < n){	if (child + 1 < n && a[child + 1]> a[child]){++child;//右孩子}if (a[child] > a[parent]){swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else {break;}}
}void HeapPop(Heap* hp)//刪除堆頂元素
{assert(hp);assert(hp->size > 0);swap(&hp->a[0], &hp->a[hp->size - 1]);hp->size--;//刪除最后一個數據AdjustDown(hp->a, hp->size, 0);//向下調整
}
5.3.2. 復雜度分析
  • 時間復雜度:假設有N個節點,高度為h,2h -1=N。至少調整log2(N+1)-1次,所以時間復雜度為logN。
  • 空間復雜度:沒有開辟額外的空間,空間復雜度為O(1)。

5.4. 獲取堆頂元素

5.4.1. 代碼實現
HpDataType HeapTop(Heap* hp)//獲取堆頂元素
{assert(hp);assert(hp->size > 0);return hp->a[0];
}
5.4.2. 復雜度分析
  • 時間復雜度:沒有額外的時間消耗,時間復雜度為O(1)。
  • 空間復雜度:沒有額外的空間消耗,空間復雜度為O(1)。

5.5. 獲取堆的元素個數

5.5.1. 代碼實現
size_t HeapSize(Heap* hp)//堆的大小
{assert(hp);return hp->size;
}
5.5.2. 復雜度分析
  • 時間復雜度:沒有額外的時間消耗,時間復雜度為O(1)。
  • 空間復雜度:沒有額外的空間消耗,空間復雜度為O(1)。

5.6. 判斷堆是否為空

5.6.1. 代碼實現
bool HeapEmpty(Heap* hp)//判斷堆是否為空
{assert(hp);return hp->size == 0;
}
5.6.2. 復雜度分析
  • 時間復雜度:沒有額外的時間消耗,時間復雜度為O(1)。
  • 空間復雜度:沒有額外的空間消耗,空間復雜度為O(1)。

5.7. 輸出堆

5.7.1. 代碼實現
void HeapDisplay(Heap* hp)//堆的打印
{for (int i = 0; i < hp->size; ++i){printf("%d ", hp->a[i]);}printf("\n");
}
5.7.2. 復雜度分析
  • 時間復雜度:遍歷整個數組,時間復雜度為O(N)。
  • 空間復雜度:沒有額外的空間消耗,空間復雜度為O(1)。

5.8. 建堆

5.8.1. 代碼實現
void HeapCreatUp(Heap* hp,HpDataType* arr,int n)//向上調整建堆
{assert(hp && arr);for (int i = 0; i < n; i++){HeapPush(hp, arr[i]);}
}
void HeapCreatDown(Heap* hp, HpDataType* arr, int n)//向下調整建堆
{assert(hp && arr);HpDataType* tmp = (HpDataType*)malloc(sizeof(HpDataType) * n);if (tmp == NULL){perror("malloc fail");exit(-1);}hp->a = tmp;memcpy(hp->a, arr, sizeof(HpDataType) * n);hp->size = n;hp->capacity = n;for (int i = ((n - 1) - 1) / 2; i >= 0; i--)//從最后一個元素開始{AdjustDown(hp->a, n, i);}
}
5.8.2. 復雜度分析

假設高度為h,節點個數為N。如果是向上調整建堆:

img

F ( N ) = 2 1 × 1 + 2 2 × 2 + . . . + 2 h ? 1 × ( h ? 1 ) 2 F ( N ) = 2 2 × 1 + 2 3 × 2 + . . . + 2 h ? 1 × ( h ? 1 ) + 2 h × ( h ? 1 ) 2 F ( N ) ? F ( N ) = ? 2 1 ? 2 2 ? 2 3 ? . . . 2 h ? 1 + 2 h × ( h ? 1 ) = ? 2 h + 2 ? 2 h + 2 h × h F ( N ) = 2 h × ( h ? 2 ) + 2 , N = 2 h ? 1 F ( N ) = ( N + 1 ) × ( l o g 2 ( N + 1 ) ? 2 ) + 2 F(N)=2^1×1+2^2×2+...+2^{h-1}×(h-1)\\ 2F(N)=2^2×1+2^3×2+...+2^{h-1}×(h-1)+2^h×(h-1)\\ 2F(N)-F(N)=-2^1-2^2-2^3-...2^{h-1}+2^h×(h-1)=-2^h+2-2^h+2^h×h\\ F(N)=2^h×(h-2)+2,N=2^h-1\\ F(N)=(N+1)×(log2(N+1)-2)+2 F(N)=21×1+22×2+...+2h?1×(h?1)2F(N)=22×1+23×2+...+2h?1×(h?1)+2h×(h?1)2F(N)?F(N)=?21?22?23?...2h?1+2h×(h?1)=?2h+2?2h+2h×hF(N)=2h×(h?2)+2,N=2h?1F(N)=(N+1)×(log2(N+1)?2)+2

如果是向下調整建堆:

img
F ( N ) = 2 h ? 2 × 1 + 2 h ? 3 × 2 + . . . + 2 0 × ( h ? 1 ) 2 F ( N ) = 2 h ? 1 × 1 + 2 h ? 2 × 2 + . . . + 2 1 × ( h ? 1 ) 2 F ( N ) ? F ( N ) = 2 h ? 1 + 2 h ? 2 + . . . 2 1 ? 2 0 × ( h ? 1 ) = 2 h ? 1 ? h F ( N ) = 2 h ? 1 ? h , N = 2 h ? 1 F ( N ) = N ? l o g 2 ( N + 1 ) F(N)=2^{h-2}×1+2^{h-3}×2+...+2^0×(h-1)\\ 2F(N)=2^{h-1}×1+2^{h-2}×2+...+2^1×(h-1)\\ 2F(N)-F(N)=2^{h-1}+2^{h-2}+...2^1-2^0×(h-1)=2^h-1-h\\ F(N)=2^h-1-h,N=2^h-1\\ F(N)=N-log2(N+1) F(N)=2h?2×1+2h?3×2+...+20×(h?1)2F(N)=2h?1×1+2h?2×2+...+21×(h?1)2F(N)?F(N)=2h?1+2h?2+...21?20×(h?1)=2h?1?hF(N)=2h?1?h,N=2h?1F(N)=N?log2(N+1

  • 時間復雜度:向上調整建堆最后一排調整h-1次,倒數第二排調整h-2次…時間復雜度為NlogN。向下調整建堆倒數第二排調整1次,倒數第二排調整2…第一排調整h-1次。時間復雜為O(N)。
  • 空間復雜度:無論是向上調整建堆還是向下調整建堆都需開辟N個空間,所以空間復雜度為O(N)。

5.9. 銷毀堆

5.9.1. 代碼實現
void HeapDestroy(Heap* hp)//銷毀堆
{assert(hp);free(hp->a);hp->size = hp->capacity = 0;
}
5.9.2. 復雜度分析
  • 時間復雜度:沒有額外的時間消耗,時間復雜度為O(1)。
  • 空間復雜度:沒有額外的空間消耗,空間復雜度為O(1)。

5.10. 完整代碼

5.10.1. Heap.h
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
typedef int HpDataType;
typedef struct Heap 
{HpDataType* a;//存儲數據int size;//大小int capacity;//容量
}Heap;
void HeapInit(Heap* hp);//堆的初始化
void AdjustUp(Heap* hp, int child);//向上調整
void HeapPush(Heap* hp, HpDataType x);//堆的插入
bool HeapEmpty(Heap* hp);//判斷堆是否為空
size_t HeapSize(Heap* hp);//堆的大小
void AdjustDown(int* a, int n, int parent);//向下調整
void HeapPop(Heap* hp);//刪除堆頂元素
HpDataType HeapTop(Heap* hp);//獲取堆頂元素
void HeapDisplay(Heap* hp);//堆的打印
void HeapDestroy(Heap* hp);//銷毀堆
void HeapCreatUp(Heap* hp,HpDataType* arr, int n);//向上調整建堆
void HeapCreatDown(Heap* hp,HpDataType* arr, int n);//向下調整建堆
5.10.2. Heap.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
void HeapInit(Heap* hp)//堆的初始化
{assert(hp);hp->a = NULL;hp->size = hp->capacity = 0;
}
void swap(HpDataType* x1, HpDataType* x2)
{HpDataType tmp = *x1;*x1 = *x2;*x2 = tmp;
}
void AdjustUp(Heap* hp, int child)//向上調整
{int parent = (child - 1) / 2;while (child > 0){if (hp->a[child] > hp->a[parent]){swap(&hp->a[child], &hp->a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}
void HeapPush(Heap* hp, HpDataType x)//堆的插入
{assert(hp);if (hp->size == hp->capacity){int newCapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;HpDataType* tmp = (HpDataType*)realloc(hp->a, newCapacity * sizeof(HpDataType));if (tmp == NULL){perror("realloc fail");exit(-1);}hp->a = tmp;hp->capacity = newCapacity;}hp->a[hp->size] = x;hp->size++;AdjustUp(hp, hp->size - 1);//向上調整
}
void AdjustDown(int* a, int n, int parent)//向下調整
{int child = parent * 2 + 1;//默認左孩子更大while (child < n){	if (child + 1 < n && a[child + 1]> a[child]){++child;//右孩子}if (a[child] > a[parent]){swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else {break;}}
}void HeapPop(Heap* hp)//刪除堆頂元素
{assert(hp);assert(hp->size > 0);swap(&hp->a[0], &hp->a[hp->size - 1]);hp->size--;//刪除最后一個數據AdjustDown(hp->a, hp->size, 0);//向下調整
}HpDataType HeapTop(Heap* hp)//獲取堆頂元素
{assert(hp);assert(hp->size > 0);return hp->a[0];
}bool HeapEmpty(Heap* hp)//判斷堆是否為空
{assert(hp);return hp->size == 0;
}size_t HeapSize(Heap* hp)//堆的大小
{assert(hp);return hp->size;
}void HeapDisplay(Heap* hp)//堆的打印
{for (int i = 0; i < hp->size; ++i){printf("%d ", hp->a[i]);}printf("\n");
}
void HeapCreatUp(Heap* hp,HpDataType* arr,int n)//向上調整建堆
{assert(hp && arr);for (int i = 0; i < n; i++){HeapPush(hp, arr[i]);}
}
void HeapCreatDown(Heap* hp, HpDataType* arr, int n)//向下調整建堆
{assert(hp && arr);HpDataType* tmp = (HpDataType*)malloc(sizeof(HpDataType) * n);if (tmp == NULL){perror("malloc fail");exit(-1);}hp->a = tmp;memcpy(hp->a, arr, sizeof(HpDataType) * n);hp->size = n;hp->capacity = n;for (int i = ((n - 1) - 1) / 2; i >= 0; i--)//從最后一個元素開始{AdjustDown(hp->a, n, i);}
}
void HeapDestroy(Heap* hp)//銷毀堆
{assert(hp);free(hp->a);hp->size = hp->capacity = 0;
}

6. Top-K問題

6.1. 問題分析

Top-K問題簡單來說就是求數據結合中前K個最大的元素或者最小的元素,一般情況下數據量都比較大。這個問題在我們日常生活中非常常見,比如說:游戲中活躍度前十的玩家,世界五百強企業等等。

解決這個問題常見的思路就是遍歷或者排序,但是當數據量較大時這種方法就并不適用了。這時我們就需要建堆來處理,具體操作方法如下:

  1. 用數據集合中前K個元素來建堆。
  • 前k個最大的元素,則建小堆。
  • 前k個最小的元素,則建大堆。
  • 用剩余的N - K個元素依次與堆頂元素來比較,不滿足條件則替換堆頂元素。
void TopK(int* a, int n, int k)
{//建堆int* kminHeap = (int*)malloc(sizeof(int) * k);if (kminHeap == NULL){perror("malloc fail");exit(-1);}//將前k個數據放入堆中for (int i = 0; i < k; i++){kminHeap[i] = a[i];}//向下調整法建小堆for (int i = (k - 1 - 1) / 2; i >= 0; i--){AdjustDown(kminHeap, k, i);}//依次比較for (int i = k; i < n; i++){if (a[i] > kminHeap[0]){kminHeap[0] = a[i];AdjustDown(kminHeap, k, 0);}}for (int i = 0; i < k; i++){printf("%d ", kminHeap[i]);}printf("\n");free(kminHeap);
}
void TestTopk()
{int n = 10000;int* a = (int*)malloc(sizeof(int) * n);srand(time(0));for (size_t i = 0; i < n; ++i){a[i] = rand() % 1000000;}a[5] = 1000000 + 1;a[1231] = 1000000 + 2;a[531] = 1000000 + 3;a[5121] = 1000000 + 4;a[115] = 1000000 + 5;a[2335] = 1000000 + 6;a[9999] = 1000000 + 7;a[76] = 1000000 + 8;a[423] = 1000000 + 9;a[3144] = 1000000 + 10;TopK(a, n, 10);
}

img

6.2. 復雜度分析

  • 時間復雜度:建堆時間為K,向下調整的最壞時間為(N-K)*logK。所以時間復雜度為NlogK。
  • 空間復雜度:建堆會開辟K的個空間,所以空間復雜度為logK。

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

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

相關文章

C++ QT設計模式 (第二版)

第3章 Qt簡介 3.2 Qt核心模塊 Qt是一個大庫&#xff0c;由數個較小的庫或者模塊組成&#xff0c;最為常見的如下&#xff1a;core、gui、xml、sql、phonon、webkit&#xff0c;除了core和gui&#xff0c;這些模塊都需要在qmake的工程文件中啟用 QTextStream 流&#xff0c;Qdat…

在buildroot中自動給kernel打補丁

我的這個buildroot是管理在git上面的&#xff0c;所以這里我直接使用git format-patch 生成patch。 下面我詳細列舉一下步驟 1&#xff0c;將沒有修改的kernel復制出來一份&#xff0c;進入kernel目錄&#xff0c;執行git init&#xff0c;add所有文件并commit 2&#xff0c…

2024年高考倒計時精品網頁

2024年高考倒計時精品網頁 前言效果圖部分代碼領取源碼下期更新預報 前言 隨著季風輕輕掠過&#xff0c;歲月如梭&#xff0c;再次迎來了這個屬于青春與夢想交匯的時刻——高考。這是一場知識的較量&#xff0c;更是一次意志的考驗。在這最后的沖刺階段&#xff0c;每一刻都顯…

可視化 FlowChart 0.4.1 最強的拖拽組件

主要解決以及目標&#xff1a; ti-flowchart 能滿足 二次開發的大部分需求。 下發GIF圖可見&#xff0c;左邊的模塊A 由二次開發人員設計&#xff0c;通過向flowchart注冊模塊Dom&#xff0c;實現符合拖拽&#xff0c;編輯&#xff0c;布局&#xff0c;以及響應事件上拋。 實…

vaspkit 畫 Charge-Density Difference

(echo 314;echo $(cat 1))|vaspkit 文件1提前寫好使用的CHGCAR路徑 SPIN_DW.vasp ../ML2scf/SPIN_DW.vasp ../ML1scf/SPIN_DW.vasp POSite and negative 默認為blue,and 青色 (RGB 30 245 245) 正值&#xff1a;blue 。負值&#xff1a;青色 RGB 30 245 245。 提示&…

(深度估計學習)Win11復現DepthFM

目錄 1. 系統配置2. 拉取代碼&#xff0c;配置環境3.開始深度預測4.運行結果 論文鏈接&#xff1a;https://depthfm.github.io/ 講解鏈接&#xff1a;https://www.php.cn/faq/734404.html 1. 系統配置 本人系統&#xff1a;Win11 CUDA12.2 python3.11.5 這里附上幾個CUDA安裝鏈…

[Cesium]Cesium基礎學習——Primitive

Cesium開發高級篇 | 01空間數據可視化之Primitive - 知乎 Primitive由兩部分組成&#xff1a;幾何體&#xff08;Geometry&#xff09;和外觀&#xff08;Appearance&#xff09;。幾何體定義了幾何類型、位置和顏色&#xff0c;例如三角形、多邊形、折線、點、標簽等&#xff…

EM算法與變分推斷

符號說明 x x x&#xff1a;已觀測變量的集合 { x 1 , x 2 , x 3 , . . . , x N } \{x_1,x_2,x_3,...,x_N\} {x1?,x2?,x3?,...,xN?}&#xff0c;長度為 N N N z z z&#xff1a;隱變量&#xff08;未觀測變量&#xff09; θ \theta θ&#xff1a;分布參數 ( x , z ) (x,…

pdffactory pro8.0虛擬打印機(附注冊碼)

PdfFactory pro是一款非常受歡迎的PDF虛擬打印機&#xff0c;可以幫助用戶將你的其他文檔保存為PDF格式。請為用戶提供打印/發送/加密等多種實用功能&#xff0c;以及一套完善的PDF打印方案。 使用說明 下載pdfFactory Pro壓縮包&#xff0c;解壓后&#xff0c;雙擊exe文件&am…

LeetCode_LCR002做題總結(可變字符序列使用)

LCR 002. 二進制求和 方法一方法二遺落知識點字符串長度stringStringBuffer && StringBuilder 方法一 轉換成十進制數&#xff0c;求和之后再轉換成二進制數 class Solution {public String addBinary(String a, String b) {return Integer.toBinaryString(Integer.p…

算法提高之木棒

算法提高之木棒 核心思想&#xff1a;dfs 剪枝優化 1.搜索順序優化&#xff1a;len從小到大遍歷2**.剪枝(失敗后)&#xff1a;** (1) 跳過所有和第i根木棍相同長度的木棍(2) 如果當前木棍是新木棒的第一根就失敗了 則之后不會搜到方案 return false(3) 下一根失敗但是上一根成…

java獲取到泛型信息后,需要包裝到另一個父類型中。比如讀取類型R,包裝成Res<R>

問題 對于json解析來說&#xff0c;我們一般是通過jackson的TypeReference或者XXX.class來制定類型&#xff08;其他json框架同理&#xff09;&#xff0c;比如下列代碼&#xff1a; ResponseBody<XxxClass> body JsonUtils.parseObject(response, new TypeReference&…

vue + element-plus項目做管理系統常用的組件,以及一些方便開發的設置

1.簡化路徑 //vite.consfig.ts import { defineConfig, ConfigEnv } from vite import vue from vitejs/plugin-vue import path from path export default defineConfig(({ command }: ConfigEnv) > {return {plugins: [vue(),],resolve: {alias: {: path.resolve(__dirn…

EEL中 python端的函數名是如何傳遞給js端的

python端的函數名是如何傳遞給js端的 核心步驟&#xff1a;將函數名列表注入到動態生成的 eel.js 中&#xff0c;這樣前端一開始引用的eel.js本身已經包含有py_function的函數名列表了。你打開開發者工具看看瀏覽器中的 eel.js文件源代碼就知道了。 具體實現&#xff1a; # 讀…

全面解析OpenAI的新作——GPT-4o

5月14日凌晨1點、太平洋時間的上午 10 點&#xff0c;OpenAI的GPT-4o的橫空出世&#xff0c;再次鞏固了其作為行業顛覆者的地位。GPT-4o的發布不僅僅是一個產品的揭曉&#xff0c;它更像是向世界宣告AI技術已邁入了一個全新的紀元&#xff0c;連OpenAI的領航者薩姆奧特曼也不禁…

樓宇智慧公廁建設新方案-集成更簡單!成本價更低!

在當今的大廈和寫字樓中&#xff0c;公廁面臨著諸多痛點。 辦公樓公廁常常存在廁位難找的問題&#xff0c;使用者不得不花費時間逐一查看&#xff0c;導致效率低下&#xff1b;環境質量也令人擔憂&#xff0c;異味、臟污等情況時有發生&#xff0c;影響使用者的心情和健康&…

【simulink】Scrambling 加擾

https://ww2.mathworks.cn/help/comm/ug/additive-scrambling-of-input-data-in-simulink.html 草圖 simulink 代碼圖

leetcode-11. 盛最多水的容器(雙指針)

11. 盛最多水的容器 /*** param {number[]} height* return {number}*/ var maxArea function (height) {// 時間復雜度 O(n)// 空間復雜度 O(1)let len height.length;let left 0,right len - 1;let res 0;while (left < right) {let area Math.min(height[left], h…

QT狀態機10-QKeyEventTransition和QMouseEventTransition的使用

1、QMouseEventTransition的使用 首先明白 QMouseEventTransition 繼承自 QEventTransition類。 關于QEventTransition類的使用,可參考 QT狀態機9-QEventTransition和QSignalTransition的使用 回顧 QT狀態機9-QEventTransition和QSignalTransition的使用 中的狀態切換代碼,如…

零基礎10 天入門 Web3之第3天

10 天入門 Web3之第3天 什么是以太坊&#xff0c;以太坊能做什么&#xff1f;Web3 是互聯網的下一代&#xff0c;它將使人們擁有自己的數據并控制自己的在線體驗。Web3 基于區塊鏈技術&#xff0c;該技術為安全、透明和可信的交易提供支持。我準備做一個 10 天的學習計劃&…