哈夫曼算法

哈夫曼算法

哈夫曼算法的一般步骤如下:
1.初始化:由给定的 个权值构造 n n n棵只有一个根节点的二叉树,得到一个二叉树集合 F F F
2.选取与合并:从二叉树集合 F F F中选取根节点权值 最小的两棵 二叉树分别作为左右子树构造一棵新的二叉树,这棵新二叉树的根节点的权值为其左、右子树根结点的权值和。
3.删除与加入:从 F F F中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到 F F F中。
4.重复 2、3 步,当集合中只剩下一棵二叉树时,这棵二叉树就是霍夫曼树。
代码

#include<stdio.h>
#include<stdlib.h>
#include<queue>
#define N 1000
using namespace std;
typedef struct HNode{
	int weight;
	HNode *lchild,*rchild;
} *Htree;

Htree createHuffmanTree(int arr[],int n){
	//构建哈夫曼树 
	Htree forest[N];
	Htree root=NULL;
	for(int i=0;i<n;i++){
		Htree temp;
		temp=(Htree)malloc(sizeof(HNode));
		temp->weight=arr[i];
		temp->lchild=temp->rchild=NULL;
		forest[i]=temp;
	}
	
	for(int i=0;i<n-1;i++){ //n个节点合并成一颗树需要进行n-1次合并操作
		int Min=-1,Minsub;//Min为最小树根的下标,Minsub为次小树根的下标 
		for(int j=0;j<n;j++){
			if(Min==-1&&forest[j]!=NULL){
				Min=j;
				continue;
			}
			if(forest[j]!=NULL){
				Minsub=j;
				break;
			}
		}
		for(int j=Minsub;j<n;j++){
			if(forest[j]!=NULL){
				if(forest[j]->weight<forest[Min]->weight){
					Minsub=Min;
					Min=j;
				}
				else if(forest[j]->weight<forest[Minsub]->weight)
					Minsub=j;
			}
		}
		
		printf("%d %d\n",forest[Min]->weight,forest[Minsub]->weight);
		root=(Htree)malloc(sizeof(HNode));
		root->weight=forest[Min]->weight+forest[Minsub]->weight; // 根节点的权值为两个叶子节点之和
		root->lchild=forest[Min];
		root->rchild=forest[Minsub];
		forest[Min]=root;//指向新树的指针赋给Min的位置 
		forest[Minsub]=NULL;//将Minsub位置赋为空 
	}
	//printf("%d\n",root->weight);
	return root;
}

int getWPL(Htree root,int len){
	//对于已建好的哈夫曼树,求其WPL 
	if(root==NULL)
		return 0;
	if(root->lchild==NULL&&root->rchild==NULL){
		return (root->weight)*len;
	}
	int left,right;
	left=getWPL(root->lchild,len+1);
	right=getWPL(root->rchild,len+1);
	return left+right;
}
int getWPL(int arr[], int n) {  
	// 对于未建好的哈夫曼树,直接求其WPL
	//树的WPL==所有非叶子结点之和 
	priority_queue<int, vector<int>, greater<int>> huffman;  //小根堆
	for (int i = 0; i < n; i++) huffman.push(arr[i]);
	
	int res = 0;
	for (int i = 0; i < n - 1; i++) {
		int x = huffman.top();
		huffman.pop();
		int y = huffman.top();
		huffman.pop();
		int temp = x + y;
		res += temp;
		printf("%d\n",res);
		huffman.push(temp);
	}
	return res;
}
void huffmanCoding(Htree root,int len,char *cod){
	if(root!=NULL){
		if(root->lchild==NULL&&root->rchild==NULL){
			printf("权值为%d的结点的哈夫曼编码为:\n",root->weight);
			cod[len]='\0';
			printf("%s",cod);
			printf("\n");
		}
		else{
			cod[len]='0';
			huffmanCoding(root->lchild,len+1,cod);
			cod[len]='1';
			huffmanCoding(root->rchild,len+1,cod);
		}
	}
}

void Preorder(Htree tree){
	if(tree==NULL)
		return ;
	printf("%d ",tree->weight);
	Preorder(tree->lchild);
	Preorder(tree->rchild);
}

int main()
{
	int arr[6]={3,1,5,6,2,8};
	char s[100];
	Htree HuffmanTree=createHuffmanTree(arr,6);
	Preorder(HuffmanTree);
	printf("\n");
	printf("WPL:%d\n",getWPL(HuffmanTree,0));
	huffmanCoding(HuffmanTree,0,s);
	//printf("WPL2:%d\n",getWPL(arr,6));
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈夫曼算法是一种经典的压缩算法,通过构建哈夫曼树来实现无损压缩。以下是 C++ 实现代码示例: ```cpp #include <iostream> #include <queue> using namespace std; // 定义哈夫曼树节点结构体 struct Node { char data; int weight; Node *left, *right; Node(char c, int w) : data(c), weight(w), left(nullptr), right(nullptr) {} }; // 比较器,用于优先队列排序 struct Compare { bool operator()(const Node* lhs, const Node* rhs) const { return lhs->weight > rhs->weight; } }; // 建立哈夫曼树 Node* buildHuffman(const string& str) { int freq[256] = {0}; for (char c : str) { freq[c]++; } priority_queue<Node*, vector<Node*>, Compare> pq; for (int i = 0; i < 256; i++) { if (freq[i]) { pq.push(new Node(i, freq[i])); } } while (pq.size() > 1) { Node* left = pq.top(); pq.pop(); Node* right = pq.top(); pq.pop(); Node* parent = new Node(' ', left->weight + right->weight); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } // 编码表 void buildCodeTable(const Node* root, string codeTable[], string code) { if (!root) { return; } if (root->left) { buildCodeTable(root->left, codeTable, code + '0'); } if (root->right) { buildCodeTable(root->right, codeTable, code + '1'); } if (!root->left && !root->right) { codeTable[root->data] = code; } } // 压缩 string compress(const string& str, const string codeTable[]) { string compressed; for (char c : str) { compressed += codeTable[c]; } return compressed; } // 解压 string decompress(const string& compressed, const Node* root) { string decompressed; const Node* curr = root; for (char c : compressed) { curr = (c == '0') ? curr->left : curr->right; if (!curr->left && !curr->right) { decompressed += curr->data; curr = root; } } return decompressed; } int main() { string str = "hello world"; Node* root = buildHuffman(str); string codeTable[256]; buildCodeTable(root, codeTable, ""); string compressed = compress(str, codeTable); string decompressed = decompress(compressed, root); cout << "Original string: " << str << endl; cout << "Compressed string: " << compressed << endl; cout << "Decompressed string: " << decompressed << endl; return 0; } ``` 希望能对您有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值