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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

赫夫曼树的建立

發(fā)布時(shí)間:2024/1/8 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 赫夫曼树的建立 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

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

赫夫曼樹(shù)的建立

#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;//存的數(shù)據(jù)int weight;//權(quán)重int parent;//雙親的數(shù)組下標(biāo)int lchild;//左孩子的數(shù)組下標(biāo)int rchild;//右孩子的數(shù)組下標(biāo)int flag;//標(biāo)志這個(gè)節(jié)點(diǎn)是否已經(jīng)被查找到,并構(gòu)造成樹(shù)過(guò) } Hffmantree;//int select(Hffmantree* H, int n);//查找剩余未被構(gòu)造成數(shù)的節(jié)點(diǎn)中權(quán)重最小的節(jié)點(diǎn) void init_H(Hffmantree* H, int n);//初始化赫夫曼樹(shù) void create_H(Hffmantree* H, int n);//創(chuàng)建赫夫曼樹(shù) void traverse_H(Hffmantree* H, int n);//遍歷輸出赫夫曼樹(shù)int main() {int n;printf("請(qǐng)輸入該赫夫曼樹(shù)的葉子節(jié)點(diǎn)個(gè)數(shù):");scanf("%d", &n);//便于區(qū)分已有的葉子節(jié)點(diǎn)下標(biāo)和新創(chuàng)建的“根節(jié)點(diǎn)”的數(shù)組下標(biāo)Hffmantree H[M+1];int i;for (i = 1; i <= n; i++){H[i].data = 64 + i;H[i].weight = i;}//存入赫夫曼樹(shù)節(jié)點(diǎn)的數(shù)據(jù)'A','B','C','D'......for (i = n+1; i <= 2*n-1; i++){H[i].data = ' ';}init_H(H, n);traverse_H(H, n);//輸出一次初始化的赫夫曼樹(shù)create_H(H, n);traverse_H(H, n);//輸出一次構(gòu)造好的赫夫曼樹(shù) }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;}//初始化原本的葉子節(jié)點(diǎn)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;}//初始化將要構(gòu)造的“根節(jié)點(diǎn)” }int select(Hffmantree* H, int n) {int i = 0;int min=0;//存放權(quán)重最小節(jié)點(diǎn)的權(quán)重值int dex=0;//存放權(quán)重最小的節(jié)點(diǎn)的下標(biāo)for (i = 0; i <= n; i++){if (H[i].flag == 0){min = H[i].weight;dex = i;break;}}//為避免min和dex值不合理,用一個(gè)for循環(huán)找到第一個(gè)為被查找到過(guò)的節(jié)點(diǎn)的下標(biāo)和權(quán)重作為min和dex的初始化值for (i = 0; i <= n; i++){if (H[i].flag == 0){if (H[i].weight < min){min = H[i].weight;dex = i;}}}//找到最小權(quán)重的節(jié)點(diǎn)的權(quán)重值和下標(biāo)H[dex].flag = 1;//改寫(xiě)flag為1,標(biāo)志該結(jié)點(diǎn)已被查找過(guò)return dex;//返回最小權(quán)重節(jié)點(diǎn)的下標(biāo) }void create_H(Hffmantree* H, int n) {int i = n + 1;for (i = n + 1; i <= 2 * n - 1; i++)//從結(jié)構(gòu)體數(shù)組的第n-1位開(kāi)始創(chuàng)建“根節(jié)點(diǎn)”{int a;a = select(H, i - 1);//查找當(dāng)前最小權(quán)值的節(jié)點(diǎn)下標(biāo)int b;b = select(H, i - 1);//查找第二小權(quán)值的節(jié)點(diǎn)下標(biāo)(當(dāng)然它也就是查找完最小權(quán)值節(jié)點(diǎn)之后最小的權(quán)值節(jié)點(diǎn))H[i].weight = H[a].weight + H[b].weight;//存儲(chǔ)“根節(jié)點(diǎn)”的權(quán)重H[i].lchild = a;//存儲(chǔ)“根節(jié)點(diǎn)”的左孩子下標(biāo)H[i].rchild = b;//存儲(chǔ)“根節(jié)點(diǎn)”的右孩子下標(biāo)H[a].parent = i;//將左孩子的雙親下標(biāo)存入H[b].parent = i;//將右孩子的雙親下標(biāo)存入} }void traverse_H(Hffmantree* H, int n) {int i = 0;printf("當(dāng)前的赫夫曼樹(shù):\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"); }

思路


-------------------------------從一個(gè)博主那里順來(lái)的百度圖片(感謝萬(wàn)分)--------------------------------------

如圖所示

大致思路:

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

構(gòu)造步驟

借助一個(gè)結(jié)構(gòu)體數(shù)組存儲(chǔ)這個(gè)赫夫曼樹(shù),結(jié)構(gòu)體中包含權(quán)重,雙親的數(shù)組下標(biāo),左孩子的數(shù)組下標(biāo),右孩子的數(shù)組下標(biāo),一個(gè)標(biāo)志節(jié)點(diǎn)是否已被建造的flag(直接用雙親判斷也可以);

1.先初始化這個(gè)赫夫曼樹(shù):

將結(jié)構(gòu)體中所有的數(shù)據(jù)賦予0值。

2.創(chuàng)造赫夫曼樹(shù)(借助一個(gè)函數(shù)尋找最小權(quán)重的兩個(gè)節(jié)點(diǎn)):

從第n+1個(gè)數(shù)組位置開(kāi)始創(chuàng)建用來(lái)鏈接兩個(gè)葉子節(jié)點(diǎn)的“根節(jié)點(diǎn)”,在創(chuàng)建每一個(gè)“根節(jié)點(diǎn)”時(shí),要,將兩個(gè)葉子節(jié)點(diǎn)的雙親的數(shù)組下標(biāo)存入(也就是當(dāng)前這個(gè)根節(jié)點(diǎn)的下標(biāo)),要存儲(chǔ)“根節(jié)點(diǎn)”的權(quán)重,左右孩子的數(shù)組下標(biāo);在尋找最小權(quán)重的兩個(gè)葉子節(jié)點(diǎn)的函數(shù)中,每找到一個(gè)節(jié)點(diǎn)時(shí),記得將這個(gè)節(jié)點(diǎn)的flag值改為1,便于后續(xù)查找剩余節(jié)點(diǎn)中的最小節(jié)點(diǎn)時(shí),可以跳過(guò)這個(gè)節(jié)點(diǎn)。

3.遍歷輸出赫夫曼樹(shù)

很簡(jiǎn)單,直接將數(shù)組的每一位輸出即可。

總結(jié)

以上是生活随笔為你收集整理的赫夫曼树的建立的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。