哈夫曼樹(代碼實現(xiàn))

前面我們介紹了哈夫曼樹的理論實現(xiàn),現(xiàn)在介紹一下具體代碼實現(xiàn)报强。

我們先定義哈夫曼樹節(jié)點的數(shù)據(jù)結(jié)構(gòu)灸姊。

struct haffManTreeNode // 哈夫曼樹的節(jié)點
{
    char symbol;          //存儲的符號
    int weight;        //權(quán)重
    haffManTreeNode* lChild;
    haffManTreeNode* rChild;
};

struct haffManTreeRoot  //為了方便,特別定義一個根節(jié)點
{
    haffManTreeNode* next;
};

haffManTreeNode* initHaffManTreeNode(char symbol,int weight)
{
//初始化一個樹節(jié)點
    haffManTreeNode* tree = new haffManTreeNode;
    tree->lChild = NULL;
    tree->rChild = NULL;
    tree->symbol = symbol;
    tree->weight = weight;
    return tree;
}

在有了樹節(jié)點之后秉溉,我們需要一個鏈表結(jié)構(gòu)來存儲不同節(jié)點的權(quán)值力惯,并將他們排序,用這些節(jié)點來構(gòu)成我們的哈夫曼樹召嘶。

struct haffManQueue  //定義的鏈表結(jié)構(gòu)
{
    haffManTreeNode* tree;   //存儲哈夫曼樹的節(jié)點
    int weight;               //節(jié)點的權(quán)重
    haffManQueue* next;
};

struct haffManQueueHead  //為了方便父晶,定義一個頭鏈表,存儲鏈表大小
{
    int size;
    haffManQueue* next;
};

haffManQueue* initQueue()
{
//初始化鏈表節(jié)點
    haffManQueue* queue = new haffManQueue;
    queue->weight = 0;
    queue->tree = NULL;
    queue->next = NULL;
    return queue;
}

在定義完了最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)后弄跌,我們需要獲得一個數(shù)組甲喝,用來存儲一段文本的單個字符出現(xiàn)次數(shù)(權(quán)重),這里铛只,我們利用數(shù)組下標實現(xiàn)這個功能埠胖。

void getWeight(string& str,int (&weight)[256])
{
//在這里,我們傳入一個數(shù)組淳玩,與文本字符串
//注:(1)我們需要傳入數(shù)組的引用直撤,因為我們需要用形參影響實參
//(2)我們傳入的數(shù)組大小為256位,正好是全部字符的個數(shù)
    for(int i=0;i <= 255;i++)
    {
//初始化數(shù)組
        weight[i] = 0;
    }
    int count = str.length();
    for(int i=0;i < count;i++)
    {
//利用ascii碼唯一對應的數(shù)字來標注
        weight[ (char)str[i] ]++;
    }
}

接下來蜕着,我們擁有了這個權(quán)重數(shù)組谋竖,那么我們需要的就是按照哈夫曼樹的建立過程實現(xiàn)代碼。

//先定義插入函數(shù)承匣,可以更加簡單蓖乘。。悄雅。這里寫的有些復雜
//注:同樣驱敲,我們需要傳入head的引用,因為我們需要在函數(shù)中改變其中指針的值
void insertQueue(haffManQueueHead* (&head),haffManQueue* (&inserter),haffManQueue* (&address))
{
    //在address指針后面插入inserter指針宽闲,若address為NULL众眨,則表示在表頭后插入
    if(address == NULL)
    {
        inserter->next = head->next;
        head->next = inserter;
    }
    else if(address->next == NULL)
    {
        address->next = inserter;
    }
    else
    {
        inserter->next = address->next;
        address->next = inserter;
    }
}

//定義取值函數(shù),取出當前鏈表中權(quán)重最小的節(jié)點
haffManQueue* getQueueItem(haffManQueueHead* (&head))
{
    if(head->size == 0)
    {
        return NULL;
    }
    haffManQueue* temp = head->next;
    head->next = head->next->next;
    head->size--;
    return temp;
}

//由權(quán)重數(shù)組容诬,得到哈夫曼隊列
haffManQueueHead* initHaffManQueue(int (&weight)[256])
{
//建立表頭
    haffManQueueHead* head = new haffManQueueHead;
    head->next = NULL;
    head->size = 0;

    for(int i=0;i <= 255;i++)
    {
        if(weight[i] != 0)
        {
            if(head->size == 0)
            {
//如果整個鏈表沒有元素娩梨,直接插入為第一個
                haffManQueue* queue = initQueue();
                queue->tree = initHaffManTreeNode((char)i,weight[i]);
                queue->weight = queue->tree->weight;

                head->next = queue;
                head->size++;
            }
            else
            {
                haffManQueue* queue = initQueue();
                queue->tree = initHaffManTreeNode((char)i,weight[i]);
                queue->weight = queue->tree->weight;

//定義兩個指針,用來插入節(jié)點
                haffManQueue* temp = head->next;
//指向當前節(jié)點的前一個元素览徒,因為是單向鏈表狈定,無法知道之前的元素地址
                haffManQueue* preNode = NULL;   

                while(queue->weight > temp->weight && temp != NULL)
                {
                    preNode = temp;
                    temp = temp->next;
                }
                insertQueue(head,queue,preNode);
                head->size++;
            }
        }
    }
    return head;
}

//在得到哈夫曼隊列之后,我們便可以建立我們的哈夫曼樹了
haffManTreeRoot* creataHaffManTree(haffManQueueHead* (&head))
{
//初始化哈夫曼樹的根節(jié)點
    haffManTreeRoot* root = new haffManTreeRoot;
    root->next = NULL;
    if(head->size == 0)
    {
        return root;
    }
    else
    {
        while(head->size != 1)
        {
//當鏈表大小為一時,退出循環(huán)
            haffManQueue* lChild = getQueueItem(head);
            haffManQueue* rChild = getQueueItem(head);

            haffManQueue* newNode = initQueue();
//用'\0'纽什,來填充新節(jié)點的符號位措嵌,權(quán)重為兩個子樹權(quán)重之和
            newNode->tree = initHaffManTree('\0',lChild->weight+rChild->weight);
//將兩個節(jié)點作為新節(jié)點的子樹
            newNode->tree->lChild = lChild->tree;
            newNode->tree->rChild = rChild->tree;
            newNode->weight = newNode->tree->weight;

//重新插入回鏈表,排序
            if(head->size == 0)
            {
                head->next = newNode;
                head->size++;
            }
            else
            {
                haffManQueue* temp = head->next;
                haffManQueue* preNode = NULL;

                while(newNode->weight > temp->weight && temp != NULL)
                {
                    preNode = temp;
                    temp = temp->next;
                }
                insertQueue(head,newNode,preNode);
                head->size++;
            }
        }
    }
    root->next = head->next->tree;
    return root;
}

這就是我個人關(guān)于哈夫曼樹的實現(xiàn)過程芦缰。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末企巢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子让蕾,更是在濱河造成了極大的恐慌浪规,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件探孝,死亡現(xiàn)場離奇詭異笋婿,居然都是意外死亡,警方通過查閱死者的電腦和手機顿颅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門缸濒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人元镀,你說我怎么就攤上這事绍填。” “怎么了栖疑?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵讨永,是天一觀的道長。 經(jīng)常有香客問我遇革,道長卿闹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任萝快,我火速辦了婚禮锻霎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好贡歧,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布臭觉。 她就那樣靜靜地躺著仪壮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天蜀细,我揣著相機與錄音,去河邊找鬼戈盈。 笑死奠衔,一個胖子當著我的面吹牛谆刨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播归斤,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼痊夭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了官册?” 一聲冷哼從身側(cè)響起生兆,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤难捌,失蹤者是張志新(化名)和其女友劉穎膝宁,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體根吁,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡员淫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了击敌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片介返。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沃斤,靈堂內(nèi)的尸體忽然破棺而出圣蝎,到底是詐尸還是另有隱情,我是刑警寧澤衡瓶,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布徘公,位于F島的核電站,受9級特大地震影響哮针,放射性物質(zhì)發(fā)生泄漏关面。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一十厢、第九天 我趴在偏房一處隱蔽的房頂上張望等太。 院中可真熱鬧,春花似錦蛮放、人聲如沸缩抡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞻想。三九已至,卻和暖如春徘六,著一層夾襖步出監(jiān)牢的瞬間内边,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工待锈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留漠其,地道東北人。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像和屎,于是被迫代替她去往敵國和親拴驮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 樹的概述 樹是一種非常常用的數(shù)據(jù)結(jié)構(gòu)柴信,樹與前面介紹的線性表套啤,棧,隊列等線性結(jié)構(gòu)不同随常,樹是一種非線性結(jié)構(gòu) 1.樹的定...
    Jack921閱讀 4,452評論 1 31
  • 百度百科定義 給定n個權(quán)值作為n個葉子結(jié)點潜沦,構(gòu)造一棵二叉樹,若帶權(quán)路徑長度達到最小绪氛,稱這樣的二叉樹為最優(yōu)二叉樹唆鸡,也...
    scarerow閱讀 1,430評論 0 2
  • 簡介 哈夫曼樹是一種帶權(quán)路徑長度最短的二叉樹,也稱為最優(yōu)二叉樹枣察。 定義:給定 n 個權(quán)值作為 n 個葉子節(jié)點争占,構(gòu)造...
    隨時學丫閱讀 3,173評論 0 1
  • 定義指針變量,如果不賦給它地址序目,系統(tǒng)會隨機給它分配一個地址臂痕。 C++標準庫 C++ Standard Librar...
    縱我不往矣閱讀 290評論 0 1
  • 應該要把swift提上緊急日程了。 來自一線開發(fā)者的Swift學習資源推薦 2016年關(guān)于swift大牛的文章 猿...
    Funnyer閱讀 243評論 0 0