日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

赫夫曼树的建立

發布時間:2024/1/8 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 赫夫曼树的建立 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 赫夫曼樹的建立
    • 思路
      • 如圖所示
      • 大致思路:
        • 將所有具有權重的葉子節點一字排開,在其中找到的權重最小的兩個葉子節點借助一個新的節點(根)鏈接成一棵樹(一般兩個節點中權重小的為左孩子,更大的為右孩子),這個根的權重就等于那兩個葉子節點的權重之和,然后再將這個根放在那一堆還未選出的葉子節點中進行比較,再找到其中兩個最小的節點鏈接成一棵樹,反復重復上述操作,直到構建成一棵完整的赫夫曼樹(本質上就上讓權重越大的葉子節點越靠近根節點)
      • 構造步驟
        • 借助一個結構體數組存儲這個赫夫曼樹,結構體中包含權重,雙親的數組下標,左孩子的數組下標,右孩子的數組下標,一個標志節點是否已被建造的flag(直接用雙親判斷也可以);
        • 1.先初始化這個赫夫曼樹:
        • 將結構體中所有的數據賦予0值。
        • 2.創造赫夫曼樹(借助一個函數尋找最小權重的兩個節點):
        • 從第n+1個數組位置開始創建用來鏈接兩個葉子節點的“根節點”,在創建每一個“根節點”時,要,將兩個葉子節點的雙親的數組下標存入(也就是當前這個根節點的下標),要存儲“根節點”的權重,左右孩子的數組下標;在尋找最小權重的兩個葉子節點的函數中,每找到一個節點時,記得將這個節點的flag值改為1,便于后續查找剩余節點中的最小節點時,可以跳過這個節點。
        • 3.遍歷輸出赫夫曼樹
        • 很簡單,直接將數組的每一位輸出即可。

赫夫曼樹的建立

#define _CRT_SECURE_NO_WARNINGS 1 #pragma warning(disable:6031) #include<stdio.h> #include<stdlib.h> #define N 15 #define M 2*N-1 typedef struct node {char data;//存的數據int weight;//權重int parent;//雙親的數組下標int lchild;//左孩子的數組下標int rchild;//右孩子的數組下標int flag;//標志這個節點是否已經被查找到,并構造成樹過 } Hffmantree;//int select(Hffmantree* H, int n);//查找剩余未被構造成數的節點中權重最小的節點 void init_H(Hffmantree* H, int n);//初始化赫夫曼樹 void create_H(Hffmantree* H, int n);//創建赫夫曼樹 void traverse_H(Hffmantree* H, int n);//遍歷輸出赫夫曼樹int main() {int n;printf("請輸入該赫夫曼樹的葉子節點個數:");scanf("%d", &n);//便于區分已有的葉子節點下標和新創建的“根節點”的數組下標Hffmantree H[M+1];int i;for (i = 1; i <= n; i++){H[i].data = 64 + i;H[i].weight = i;}//存入赫夫曼樹節點的數據'A','B','C','D'......for (i = n+1; i <= 2*n-1; i++){H[i].data = ' ';}init_H(H, n);traverse_H(H, n);//輸出一次初始化的赫夫曼樹create_H(H, n);traverse_H(H, n);//輸出一次構造好的赫夫曼樹 }void init_H(Hffmantree *H, int n) {int i = 0;for (i = 1; i <= n; i++){H[i].parent = 0;H[i].lchild = 0;H[i].rchild = 0;H[i].flag = 0;}//初始化原本的葉子節點for (i = n + 1; i <= 2 * n - 1; i++){H[i].weight = 0;H[i].parent = 0;H[i].lchild = 0;H[i].rchild = 0;H[i].flag = 0;}//初始化將要構造的“根節點” }int select(Hffmantree* H, int n) {int i = 0;int min=0;//存放權重最小節點的權重值int dex=0;//存放權重最小的節點的下標for (i = 0; i <= n; i++){if (H[i].flag == 0){min = H[i].weight;dex = i;break;}}//為避免min和dex值不合理,用一個for循環找到第一個為被查找到過的節點的下標和權重作為min和dex的初始化值for (i = 0; i <= n; i++){if (H[i].flag == 0){if (H[i].weight < min){min = H[i].weight;dex = i;}}}//找到最小權重的節點的權重值和下標H[dex].flag = 1;//改寫flag為1,標志該結點已被查找過return dex;//返回最小權重節點的下標 }void create_H(Hffmantree* H, int n) {int i = n + 1;for (i = n + 1; i <= 2 * n - 1; i++)//從結構體數組的第n-1位開始創建“根節點”{int a;a = select(H, i - 1);//查找當前最小權值的節點下標int b;b = select(H, i - 1);//查找第二小權值的節點下標(當然它也就是查找完最小權值節點之后最小的權值節點)H[i].weight = H[a].weight + H[b].weight;//存儲“根節點”的權重H[i].lchild = a;//存儲“根節點”的左孩子下標H[i].rchild = b;//存儲“根節點”的右孩子下標H[a].parent = i;//將左孩子的雙親下標存入H[b].parent = i;//將右孩子的雙親下標存入} }void traverse_H(Hffmantree* H, int n) {int i = 0;printf("當前的赫夫曼樹:\n");for (i = 1; i <= 2 * n - 1; i++){printf("%d %c %d %d %d %d %d \n",i, H[i].data, H[i].weight, H[i].parent, H[i].lchild, H[i].rchild, H[i].flag);}//遍歷輸出printf("\n"); }

思路


-------------------------------從一個博主那里順來的百度圖片(感謝萬分)--------------------------------------

如圖所示

大致思路:

將所有具有權重的葉子節點一字排開,在其中找到的權重最小的兩個葉子節點借助一個新的節點(根)鏈接成一棵樹(一般兩個節點中權重小的為左孩子,更大的為右孩子),這個根的權重就等于那兩個葉子節點的權重之和,然后再將這個根放在那一堆還未選出的葉子節點中進行比較,再找到其中兩個最小的節點鏈接成一棵樹,反復重復上述操作,直到構建成一棵完整的赫夫曼樹(本質上就上讓權重越大的葉子節點越靠近根節點)

構造步驟

借助一個結構體數組存儲這個赫夫曼樹,結構體中包含權重,雙親的數組下標,左孩子的數組下標,右孩子的數組下標,一個標志節點是否已被建造的flag(直接用雙親判斷也可以);

1.先初始化這個赫夫曼樹:

將結構體中所有的數據賦予0值。

2.創造赫夫曼樹(借助一個函數尋找最小權重的兩個節點):

從第n+1個數組位置開始創建用來鏈接兩個葉子節點的“根節點”,在創建每一個“根節點”時,要,將兩個葉子節點的雙親的數組下標存入(也就是當前這個根節點的下標),要存儲“根節點”的權重,左右孩子的數組下標;在尋找最小權重的兩個葉子節點的函數中,每找到一個節點時,記得將這個節點的flag值改為1,便于后續查找剩余節點中的最小節點時,可以跳過這個節點。

3.遍歷輸出赫夫曼樹

很簡單,直接將數組的每一位輸出即可。

總結

以上是生活随笔為你收集整理的赫夫曼树的建立的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。