C++實現(xiàn)哈夫曼樹算法
更新時間:2020年04月27日 17:20:34 作者:ChanJose
這篇文章主要為大家詳細介紹了C++實現(xiàn)哈夫曼樹的具體代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
如何建立哈夫曼樹的,網(wǎng)上搜索一堆,這里就不寫了,直接給代碼。
1.哈夫曼樹結(jié)點類:HuffmanNode.h
#ifndef HuffmanNode_h
#define HuffmanNode_h
template <class T>
struct HuffmanNode {
T weight; // 存儲權(quán)值
HuffmanNode<T> *leftChild, *rightChild, *parent; // 左、右孩子和父結(jié)點
};
#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é)點
private:
HuffmanNode<T> *heap; // 動態(tài)數(shù)組存儲最小堆
int CurrentSize; // 目前最小堆的結(jié)點數(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é)點并在堆中刪除該結(jié)點
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 << "存儲空間分配失敗!" << endl;
exit(1);
}
*newNode = heap[0]; // 將最小結(jié)點的數(shù)據(jù)復(fù)制給newNode
heap[0] = heap[CurrentSize-1]; // 用最后一個元素填補
CurrentSize--;
ShiftDown(0, CurrentSize-1); // 從0位置開始向下調(diào)整
return newNode;
}
// 向上調(diào)整
template <class T>
void MinHeap<T>::ShiftUp(int start) {
// 從start開始,直到0或者當前值大于雙親結(jié)點的值時,調(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++; // 選兩個子女中較小者
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.哈夫曼樹實現(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é)點
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 << "存儲空間分配失??!" << 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 << "存儲空間分配失敗!" << endl;
exit(1);
}
Merge(first, second, parent); // 合并
hp.Insert(parent); // 重新插入到最小堆中
}
root = parent; // 根結(jié)點
}
// 合并
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é)點權(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 << " "; // 訪問當前結(jié)點數(shù)據(jù)
PreOrder(current->leftChild); // 遞歸遍歷左子樹
PreOrder(current->rightChild); // 遞歸遍歷右子樹
}
}
#endif /* HuffmanTree_h */
4.測試: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ù)組長度
HuffmanTree<int> tree; // Huffman樹的對象
tree.Create(arr, len); // 創(chuàng)建Huffman樹
tree.PreOrder(); // 前序遍歷Huffman樹
return 0;
}
測試結(jié)果:


以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
簡要對比C語言中的setgid()函數(shù)和setregid()函數(shù)
這篇文章主要介紹了C語言中的setgid()函數(shù)和setregid()函數(shù)的簡要對比,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-08-08

