Huffman Tree(c++实现)

/***************************************************************************************************
名称:Huffman Tree
基本概念:给定n权值作为n个叶子节点,构造一棵二叉树,若这棵二叉树的带权路径长度达到最小,则称这样的
		  二叉树为最优二叉树,也称为Huffman树。

性质:  1:不唯一性(具有相同带权节点);左右子树可以互换
		2:带权值的节点都是叶子节点
		3:huffman tree中只有叶子节点和度为2的节点,没有度为1的节点
		4:一棵有n个叶子节点的Huffman tree共有2n−1个节点,需要n−1次合并。

实现方法:1:假设有n个节点,他们的权值分别为W1.....Wn;将所有节点的合集看成一个森林,
		  2:每次在所有的森林中取出根节点最小的两个节点作为左右节点合并(小左大右),且合并后的根节点的权值是左
			 右节点之和
		  3:把合并好的节点再次加入森林中
		  4:一直重复2,3步就可以得到Huffman tree了

意义:压缩数据
****************************************************************************************************/
#pragma once

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

template<class T>
class HuffmanTreeNode
{
	T m_val;
	HuffmanTreeNode *m_left;
	HuffmanTreeNode *m_right;
	HuffmanTreeNode *m_parent;


	template<class T>
	friend class HuffmanTree;

public:

	HuffmanTreeNode(T val = T()) ://构造函数
		m_val(val),
		m_right(nullptr),
		m_parent(nullptr),
		m_left(nullptr)
	{
	}

};

template<class T>
class HuffmanTree
{
	HuffmanTreeNode<T> *m_root;
public:
	HuffmanTree():
		m_root(nullptr)
	{}
	
	HuffmanTree(vector<T> v)
	{
		m_root = getHuffManTree(v);
	}

private:

	HuffmanTreeNode<T>* getHuffManTree(vector<int> v)
	{
		vector<HuffmanTreeNode<T>*> phf(v.size());
		for (int i = 0; i < v.size(); i++)
		{
			phf[i] = new HuffmanTreeNode<T>(v[i]);
			AdjustUp(phf, i);
		}
		
		int index = phf.size() - 1;
		int count = 2;

		while (index)
		{
			swap(phf[0], phf[index--]);//左
			AdjustDown(phf, index);
			swap(phf[0], phf[index--]);//右
			AdjustDown(phf, index);

			T add = phf[index + 1]->m_val + phf[index + 2]->m_val;
			phf.push_back(new HuffmanTreeNode<T>(add));
			index++;
			swap(phf[index], phf[index + count]);

			phf[index]->m_left = phf[index + 1];
			phf[index]->m_right = phf[index + count];
			AdjustUp(phf, index);

			count += 2;
		}
		return phf[0];
	}

	void AdjustUp(vector<HuffmanTreeNode<T>*> &v, int child)//向上调整,获得小堆
	{
		int parent = (child - 1) / 2;
		while (child)
		{
			if (v[child]->m_val < v[parent]->m_val)
			{
				swap(v[child], v[parent]);
			}
			child = parent;
			parent = (child - 1) / 2;
		}
	}

	void AdjustDown(vector<HuffmanTreeNode<T>*> &v, int index, int parent = 0)//向下调整
	{
		int child = parent * 2 + 1;
		while (child <= index)
		{
			if (child + 1 <= index && v[child + 1]->m_val < v[child]->m_val)
			{
				child++;
			}
			if (v[child]->m_val < v[parent]->m_val)
			{
				swap(v[child], v[parent]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
			{
				break;
			}
		}
	}
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值