欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言實現(xiàn)哈夫曼樹的方法

 更新時間:2021年05月03日 10:46:05   作者:奮斗的龍貓  
這篇文章主要為大家詳細介紹了C語言實現(xiàn)哈夫曼樹的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了C語言實現(xiàn)哈夫曼樹的具體代碼,供大家參考,具體內(nèi)容如下

準備工作:

1、定義一個結(jié)構體,表示一個節(jié)點。其中,這個結(jié)構體有4個成員變量,分別表示是這個節(jié)點的權值,父節(jié)點及左右子節(jié)點的下標
2、定義一個整形數(shù)組,用于存放各個節(jié)點的權值
3、定義一個整形數(shù)組,用于存放哈夫曼編碼,當然也可以定義一個整形數(shù)組來存放哈夫曼編碼

構建哈夫曼樹:

1、給這個哈夫曼樹創(chuàng)建一個結(jié)構體數(shù)組,其中分配的空間是2 * n - 1,因為我們都知道哈夫曼樹的性質(zhì)有一個是:給定n個葉子節(jié)點,那么由這n個葉子節(jié)點構成 的哈夫曼樹一共含有2 * n - 1個節(jié)點。
2、結(jié)構體數(shù)組前面n個用于存放n個葉子節(jié)點,然后后面的n - 1個節(jié)點用于存放父節(jié)點。這時候,我們需要遍歷這個結(jié)構體數(shù)組,將所有的節(jié)點的進行初始化,即節(jié)點的權值就是結(jié)構體數(shù)組各個下標對應的值,然后節(jié)點的父節(jié)點及子節(jié)點的下標為-1,表示的是這個節(jié)點沒有父節(jié)點,同時也沒有子節(jié)點。
3、遍歷數(shù)組,將獲取數(shù)組中兩個最小的葉子節(jié)點,然后將他們的權值合并構成一個新節(jié)點。在這一步中,我們同時需要知道這兩個最小節(jié)點在結(jié)構體數(shù)組中的下標,只有這樣,我們才可以知道它的父節(jié)點的左右子節(jié)點的下標,在初始化父節(jié)點的時候需要用到。
4、如果已經(jīng)進行了n - 1次數(shù)操作,表明已經(jīng)構建完成了。

獲取哈夫曼編碼:

1、由于我們將所有節(jié)點的權值都賦值給了一個數(shù)組,并且哈夫曼樹中的節(jié)點的下標和這個數(shù)組的下標是一一對應的,那么我們只需要首先在數(shù)組中獲取這個數(shù)字的下標,就表示他在哈夫滿樹中的下標也是這個,然后往它的父節(jié)點方向走,如果當前節(jié)點時它父節(jié)點的右子節(jié)點,那么就將1存放到數(shù)組arr2中,否則字符將0存放到數(shù)組arr2中。重復這一步,直到當前的節(jié)點的父節(jié)點為空,及已經(jīng)遍歷到了根節(jié)點。
2、重復步驟一,存放數(shù)字的數(shù)組已經(jīng)遍歷完了,這時候已經(jīng)將所有數(shù)字的哈夫曼編碼都已經(jīng)輸出了

#include<stdio.h>
#define MAX_SIZE 1000
typedef struct NODE Node;
struct NODE{
   int weight;//節(jié)點的權值
   int parent,lchild,rchild;
};
/*
初始化或者更改節(jié)點的信息,比如,如果這個節(jié)點是一個新節(jié)點,那么
就需要將這個節(jié)點初始化成一個葉子節(jié)點,否則需要修改這個節(jié)點的父節(jié)點
*/
void initNode(Node &node,int weight,int parent,int lchild,int rchild){
    node.weight = weight;
    node.lchild = lchild;
    node.rchild = rchild;
    node.parent = parent;
}
/*
1、有n個葉子節(jié)點,那么構建哈夫曼樹的時候,需要分配n * 2 - 1個內(nèi)存空間,前n
個表示的是新輸入的葉子節(jié)點,后面n - 1表示的是葉子節(jié)點的父節(jié)點
2、遍歷這個數(shù)組,將進行初始化,即給這些節(jié)點的權值賦值,并且將他的左右子節(jié)
點、父節(jié)點賦初始值為-1,從而構建了n個葉子節(jié)點
3、遍歷數(shù)組,從而將從這個數(shù)組中跳出兩個值最小的葉子節(jié)點,同時需要標記他們的下標,從而可以知道當前最小值節(jié)點的父節(jié)點的左右子節(jié)點的下標,方便下次尋找
最小值的葉子結(jié)點的時候不會再找到已經(jīng)找過的葉子節(jié)點
4、將新節(jié)點插入到數(shù)組的最后。
5、重復3,4的操作,直到只有一個節(jié)點,那么這個節(jié)點就是哈夫曼樹的根節(jié)點
*/
void createHuffmanTree(Node *node,int *arr,int n){
    //n表示有n個葉子節(jié)點,arr數(shù)組存放的是所有葉子節(jié)點的值
   int i,j,min1,min2,x1,x2,total;//min1:第一個最小值,min2:第二個最小值,x1:第一個最小值的下標,x2:第二個最小值的下標
   for(i = 0; i < n; i++){
       initNode(node[i],arr[i],-1,-1,-1);//調(diào)用initNode方法,從而將節(jié)點進行初始化
   }
   total = n * 2 - 1;//total表示的是哈夫曼所有節(jié)點的個數(shù)
   for(i = n; i < total; i++){
        //i之所以從n開始,是因為第一個父節(jié)點這個下標(前n個節(jié)點是葉子節(jié)點)
        min1 = 65432;//定義兩個最小值
        min2 = min1;
        x1 = x2 = 0;//假設兩個最小值的下標都是0
        for(j = 0; j < i; j++){
            //判斷當前下標的節(jié)點是否為葉子節(jié)點
           if(node[j].parent == -1){
          //如果當前節(jié)點的parent等于-1,表示這個節(jié)點是一個葉子節(jié)點,那么我們需要判斷他是否一個最小節(jié)點
                if(node[j].weight < min1){
         //如果當前這個節(jié)點的值比min1小,那么我們需要更新min2,min1,同時需要更新兩者對應的下標
                    min2 = min1;
                    x2 = x1;
                    min1 = node[j].weight;
                    x1 = j;
                }else if(node[j].weight < min2){
                 /*
                 如果當前這個節(jié)點比第一個最小值要大,那么我們需要判斷
                 他是否比第二個最小值小,如果是,那么更新min2,并且更新x2
                 */
                   min2 = node[j].weight;
                   x2 = j;
                }
           }
        }
        /*
        找到兩個最小節(jié)點之后,我們需要將這兩個節(jié)點的父節(jié)點指向i,
        然后將i這個節(jié)點進行初始化,并且新節(jié)點的左子節(jié)點比右子節(jié)點小
        從而構建唯一的哈夫曼樹
        */
        node[x1].parent = i;
        node[x2].parent = i;
        initNode(node[i],min1 + min2,-1,x1,x2);//初始化合并之后的新節(jié)點
   }
}
void huffmanCode(Node *node,int child,int *str){
    //str表示的是這個葉子節(jié)點的哈夫曼編碼
    int i,parent,j = 0,e;
    parent = node[child].parent;//獲取當前這個葉子節(jié)點的父節(jié)點
    while(parent != -1){
        if(node[parent].lchild == child){
            //如果當前這個節(jié)點是父節(jié)點的左子節(jié)點,那么就將0壓入到數(shù)組中,否則將1壓入數(shù)組中
            str[j++] = 0;
        }else{
            str[j++] = 1;
        }
        child = parent;
        parent = node[child].parent;
    }
    e = j;//當退出循環(huán)的時候,j表示的是這個數(shù)的哈夫曼編碼的長度,所以需要從下標為j - 1開始逆序輸出,才是這個數(shù)的哈夫曼編碼
    for(j = e - 1; j>= 0; j--)
        printf("%d",str[j]);
    printf("\n");
}
int main(){
  Node node[MAX_SIZE];
  int arr[MAX_SIZE];//定義一個整形數(shù)組,用于存放所有葉子節(jié)點的權值
  int arr2[MAX_SIZE];//arr2用于存放一個數(shù)字的哈夫曼編碼
  int n,i,j,e;
  printf("請輸入葉子節(jié)點的個數(shù):");
  scanf("%d",&n);
  for(i = 0; i < n; i++)
    scanf("%d",&arr[i]);
  createHuffmanTree(node,arr,n);//構建哈夫曼樹
  /*
  獲取哈夫曼編碼:
  1、將遍歷數(shù)組arr,從而獲得各個葉子節(jié)點的權值以及下標
  2、通過這個下標,我們從這個節(jié)點向根節(jié)點走去,如果當前節(jié)點是父節(jié)點的左子
  節(jié)點,那么將0壓入到數(shù)組中,否則將1壓入到數(shù)組arr2中
  3、逆序輸出arr2
  */
  for(i = 0; i < n; i++){
    huffmanCode(node,i,arr2);//調(diào)用這個方法,將當前下標對應的數(shù)字的哈夫曼編碼輸出
  }
  return 0;
}

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • C++詳細講解對象的構造

    C++詳細講解對象的構造

    當在參數(shù)化構造函數(shù)中聲明對象時,必須將初始值作為參數(shù)傳遞給構造函數(shù)。對象聲明的常規(guī)方法可能不起作用。構造函數(shù)可以顯式或隱式調(diào)用,讓我們一起了解對象的構造
    2022-04-04
  • C語言實現(xiàn)BMP圖像處理(哈夫曼編碼)

    C語言實現(xiàn)BMP圖像處理(哈夫曼編碼)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)BMP圖像哈夫曼編碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C語言中sizeof函數(shù)的基本使用總結(jié)

    C語言中sizeof函數(shù)的基本使用總結(jié)

    這篇文章主要給大家介紹了關于C語言中sizeof函數(shù)的基本使用的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-03-03
  • 關于vector迭代器失效的幾種情況總結(jié)

    關于vector迭代器失效的幾種情況總結(jié)

    下面小編就為大家?guī)硪黄P于vector迭代器失效的幾種情況總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • C++二維數(shù)組螺旋加密信息

    C++二維數(shù)組螺旋加密信息

    大家好,本篇文章主要講的是C++二維數(shù)組螺旋加密信息,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • C++實現(xiàn)LeetCode(211.添加和查找單詞-數(shù)據(jù)結(jié)構設計)

    C++實現(xiàn)LeetCode(211.添加和查找單詞-數(shù)據(jù)結(jié)構設計)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(211.添加和查找單詞-數(shù)據(jù)結(jié)構設計),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C語言實現(xiàn)循環(huán)鏈表

    C語言實現(xiàn)循環(huán)鏈表

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)循環(huán)鏈表,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • C++中變量進行初始化的3種方法

    C++中變量進行初始化的3種方法

    本文主要介紹了C++中變量進行初始化的3種方法,包括用"=",構造函數(shù)初始化以及統(tǒng)一初始化這三種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,著小編來一起學習學習吧
    2024-02-02
  • C++如何實現(xiàn)廣義表詳解

    C++如何實現(xiàn)廣義表詳解

    廣義表是非線性結(jié)構,其定義是遞歸的。那么下面跟著小編一起看看如何用C++實現(xiàn)廣義表,有需要的可以參考借鑒。
    2016-08-08
  • C++中指針和引用的區(qū)別詳解

    C++中指針和引用的區(qū)別詳解

    這篇文章主要介紹了C++中指針和引用的區(qū)別詳解的相關資料,需要的朋友可以參考下
    2017-02-02

最新評論