C++實(shí)現(xiàn)哈夫曼樹算法
如何建立哈夫曼樹的,網(wǎng)上搜索一堆,這里就不寫了,直接給代碼。
1.哈夫曼樹結(jié)點(diǎn)類:HuffmanNode.h
#ifndef HuffmanNode_h #define HuffmanNode_h template <class T> struct HuffmanNode { T weight; // 存儲(chǔ)權(quán)值 HuffmanNode<T> *leftChild, *rightChild, *parent; // 左、右孩子和父結(jié)點(diǎn) }; #endif /* HuffmanNode_h */
2.哈夫曼樹最小堆:HuffmanMinHeap.h
#ifndef HuffmanMinHeap_h #define HuffmanMinHeap_h #include "HuffmanNode.h" #include <iostream> using namespace std; const int DefaultSize = 100; template <class T> class MinHeap { public: MinHeap(); // 構(gòu)造函數(shù) ~MinHeap(); // 析構(gòu)函數(shù) void Insert(HuffmanNode<T> *current); // 插入 HuffmanNode<T> *getMin(); // 獲取最小結(jié)點(diǎn) private: HuffmanNode<T> *heap; // 動(dòng)態(tài)數(shù)組存儲(chǔ)最小堆 int CurrentSize; // 目前最小堆的結(jié)點(diǎn)數(shù) void ShiftUp(int start); // 向上調(diào)整 void ShiftDown(int start, int m); // 下滑 }; // 構(gòu)造函數(shù) template <class T> MinHeap<T>::MinHeap() { heap = new HuffmanNode<T>[DefaultSize]; // 創(chuàng)建堆空間 CurrentSize = 0; } // 析構(gòu)函數(shù) template <class T> MinHeap<T>::~MinHeap() { delete []heap; // 釋放空間 } // 插入 template <class T> void MinHeap<T>::Insert(HuffmanNode<T> *current) { if(CurrentSize == DefaultSize) { cout << "堆已滿" << endl; return; } // 把current的數(shù)據(jù)復(fù)制到“數(shù)組末尾” heap[CurrentSize] = *current; // 向上調(diào)整堆 ShiftUp(CurrentSize); CurrentSize++; } // 獲取最小結(jié)點(diǎn)并在堆中刪除該結(jié)點(diǎn) template <class T> HuffmanNode<T> *MinHeap<T>::getMin() { if(CurrentSize == 0) { cout << "堆已空!" << endl; return NULL; } HuffmanNode<T> *newNode = new HuffmanNode<T>(); if(newNode == NULL) { cerr << "存儲(chǔ)空間分配失??!" << endl; exit(1); } *newNode = heap[0]; // 將最小結(jié)點(diǎn)的數(shù)據(jù)復(fù)制給newNode heap[0] = heap[CurrentSize-1]; // 用最后一個(gè)元素填補(bǔ) CurrentSize--; ShiftDown(0, CurrentSize-1); // 從0位置開始向下調(diào)整 return newNode; } // 向上調(diào)整 template <class T> void MinHeap<T>::ShiftUp(int start) { // 從start開始,直到0或者當(dāng)前值大于雙親結(jié)點(diǎn)的值時(shí),調(diào)整堆 int j = start, i = (j-1)/2; // i是j的雙親 HuffmanNode<T> temp = heap[j]; while(j > 0) { if(heap[i].weight <= temp.weight) break; else { heap[j] = heap[i]; j = i; i = (j - 1) / 2; } } heap[j] = temp; } // 向下調(diào)整 template <class T> void MinHeap<T>::ShiftDown(int start, int m) { int i = start, j = 2 * i + 1; // j是i的左子女 HuffmanNode<T> temp = heap[i]; while(j <= m) { if(j < m && heap[j].weight > heap[j+1].weight) j++; // 選兩個(gè)子女中較小者 if(temp.weight <= heap[j].weight) break; else { heap[i] = heap[j]; i = j; j = 2 * j + 1; } } heap[i] = temp; } #endif /* HuffmanMinHeap_h */
3.哈夫曼樹實(shí)現(xiàn):HuffmanTree.h
#ifndef HuffmanTree_h #define HuffmanTree_h #include "HuffmanMinHeap.h" #include "HuffmanNode.h" template <class T> class HuffmanTree { public: HuffmanTree(); // 構(gòu)造函數(shù) ~HuffmanTree(); // 析構(gòu)函數(shù) void Create(T w[], int n); // 創(chuàng)建哈夫曼樹 void Merge(HuffmanNode<T> *first, HuffmanNode<T> *second, HuffmanNode<T> *parent); // 合并 void PreOrder(); // 前序遍歷Huffman樹 private: HuffmanNode<T> *root; // 根結(jié)點(diǎn) void Destroy(HuffmanNode<T> *current); // 銷毀哈夫曼樹 void PreOrder(HuffmanNode<T> *current); // 前序遍歷Huffman樹 }; // 構(gòu)造函數(shù) template <class T> HuffmanTree<T>::HuffmanTree() { root = NULL; } // 析構(gòu)函數(shù) template <class T> HuffmanTree<T>::~HuffmanTree() { Destroy(root); // 銷毀哈夫曼樹 } // 銷毀哈夫曼樹 template <class T> void HuffmanTree<T>::Destroy(HuffmanNode<T> *current) { if(current != NULL) { // 不為空 Destroy(current->leftChild); // 遞歸銷毀左子樹 Destroy(current->rightChild); // 遞歸銷毀右子樹 delete current; // 釋放空間 current = NULL; } } // 創(chuàng)建哈夫曼樹 template <class T> void HuffmanTree<T>::Create(T w[], int n) { int i; MinHeap<T> hp; // 使用最小堆存放森林 HuffmanNode<T> *first, *second, *parent = NULL; HuffmanNode<T>*work = new HuffmanNode<T>(); if(work == NULL) { cerr << "存儲(chǔ)空間分配失??!" << endl; exit(1); } for(i = 0; i < n; i++) { work->weight = w[i]; work->leftChild = work->rightChild = work->parent = NULL; hp.Insert(work); // 插入到最小堆中 } for(i=0; i < n-1; i++) { // 做n-1趟,形成Huffman樹 first = hp.getMin(); // 獲取權(quán)值最小的樹 second = hp.getMin(); // 獲取權(quán)值次小的樹 parent = new HuffmanNode<T>(); if(parent == NULL) { cerr << "存儲(chǔ)空間分配失??!" << endl; exit(1); } Merge(first, second, parent); // 合并 hp.Insert(parent); // 重新插入到最小堆中 } root = parent; // 根結(jié)點(diǎn) } // 合并 template <class T> void HuffmanTree<T>::Merge(HuffmanNode<T> *first, HuffmanNode<T> *second, HuffmanNode<T> *parent) { parent->leftChild = first; // 左子樹 parent->rightChild = second; // 右子樹 parent->weight = first->weight + second->weight; // 父結(jié)點(diǎn)權(quán)值 first->parent = second->parent = parent; // 父指針 } // 前序遍歷Huffman樹 template <class T> void HuffmanTree<T>::PreOrder() { PreOrder(root); } // 前序遍歷Huffman樹 template <class T> void HuffmanTree<T>::PreOrder(HuffmanNode<T> *current) { if(current != NULL) { cout << current->weight << " "; // 訪問當(dāng)前結(jié)點(diǎn)數(shù)據(jù) PreOrder(current->leftChild); // 遞歸遍歷左子樹 PreOrder(current->rightChild); // 遞歸遍歷右子樹 } } #endif /* HuffmanTree_h */
4.測(cè)試:main.cpp
#include "HuffmanTree.h" int main(int argc, const char * argv[]) { int arr[] = {7, 5, 2, 4}; int len = sizeof(arr) / sizeof(arr[0]); // 數(shù)組長(zhǎng)度 HuffmanTree<int> tree; // Huffman樹的對(duì)象 tree.Create(arr, len); // 創(chuàng)建Huffman樹 tree.PreOrder(); // 前序遍歷Huffman樹 return 0; }
測(cè)試結(jié)果:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- C++深入講解哈夫曼樹
- C++詳解哈夫曼樹的概念與實(shí)現(xiàn)步驟
- C++實(shí)現(xiàn)哈夫曼樹的方法
- C++實(shí)現(xiàn)哈夫曼樹編碼解碼
- C++數(shù)據(jù)結(jié)構(gòu)與算法之哈夫曼樹的實(shí)現(xiàn)方法
- C++ 哈夫曼樹對(duì)文件壓縮、加密實(shí)現(xiàn)代碼
- C++數(shù)據(jù)結(jié)構(gòu)之文件壓縮(哈夫曼樹)實(shí)例詳解
- 解析C++哈夫曼樹編碼和譯碼的實(shí)現(xiàn)
- C++實(shí)現(xiàn)哈夫曼樹簡(jiǎn)單創(chuàng)建與遍歷的方法
- C++使用數(shù)組來實(shí)現(xiàn)哈夫曼樹
相關(guān)文章
C++ abs函數(shù)實(shí)際應(yīng)用詳解
本文我們來講C++的abs函數(shù)以及實(shí)戰(zhàn)運(yùn)用,C++中的abs函數(shù)。在C++中使用abs函數(shù)要注意存在兩種版本,一種是在stdlmb.h中定義的版本,另一個(gè)是在cmath頭文件中定義的。夷實(shí)上在stdlib.h文件是C的函數(shù),而cmath中的是C++版本2022-08-08c++ 寫注冊(cè)表方式讓程序開機(jī)自啟動(dòng)
這篇文章主要介紹了c++ 寫注冊(cè)表方式讓程序開機(jī)自啟動(dòng),需要的朋友可以參考下2017-09-09C++實(shí)現(xiàn)動(dòng)態(tài)煙花效果
這篇文章主要介紹了利用C++實(shí)現(xiàn)的放煙花程序,用到了EGE圖形庫(kù),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++有一定幫助,需要的可以參考一下2022-01-01C++中vector容器的常用操作方法實(shí)例總結(jié)
vector容器一般被用作創(chuàng)建動(dòng)態(tài)數(shù)組,動(dòng)態(tài)數(shù)組就像Python中的list結(jié)構(gòu)一樣,可以比普通數(shù)組擁有更豐富操作方法,下面就為大家整理了一些最常用的操作:2016-05-05簡(jiǎn)要對(duì)比C語(yǔ)言中的setgid()函數(shù)和setregid()函數(shù)
這篇文章主要介紹了C語(yǔ)言中的setgid()函數(shù)和setregid()函數(shù)的簡(jiǎn)要對(duì)比,是C語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-08-08判斷給定的圖是不是有向無(wú)環(huán)圖實(shí)例代碼
判斷給定的圖是不是是有向無(wú)環(huán)圖,方法是應(yīng)用拓?fù)渑判颍a如下2013-05-05C語(yǔ)言實(shí)現(xiàn)一個(gè)閃爍的圣誕樹
本文詳細(xì)講解了C語(yǔ)言實(shí)現(xiàn)一個(gè)閃爍的圣誕樹,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12