霍夫曼树

输入
一串小写字母组成的字符串(不超过1000000)。
输出
输出这个字符串通过Huffman编码后的长度。
样例
输入
abcdabcaba

输出
19

限制
1s, 1024KiB for each test case.
提示
样例中,‘a’ 出现了4次,‘b’ 出现了3次,‘c’ 出现了2次,‘d’ 出现了1次
编码为: ‘a’ : 0 ‘b’ : 10 ‘c’ : 110 ‘d’ : 111

#include<iostream>
#include<string>
using namespace std;
struct HuffmanNode//定义霍夫曼节点 
{
   int element;
   HuffmanNode *leftChild,   // left subtree
                     *rightChild;  // right subtree
   int weight;
   HuffmanNode(){}
};
template <class T>//链表结构 
struct chainNode 
{
   // data members
   T element;
   chainNode<T> *next;

   // methods
   chainNode() {}
   chainNode(const T& element)
      {this->element = element;}
   chainNode(const T& element, chainNode<T>* next)
      {this->element = element;
       this->next = next;}
};
template<class T>
class linkedQueue 
{
   public:
      linkedQueue(int initialCapacity = 10)
            {queueFront = NULL; queueSize = 0;}//初始化队列 
      ~linkedQueue();//析构函数 
      bool empty() const 
           {return queueSize == 0;}
      int size() const
          {return queueSize;}
      T& front()//队首 
         {
            if (queueSize == 0)
              exit(1);
            return queueFront->element;
         }
      T& back()//队尾 
         {
            if (queueSize == 0)
               exit(1);
            return queueBack->element;
         }
      void pop();//删除队首 
      void push(const T&);//插入到队尾 
   private:
      chainNode<T>* queueFront;  
      chainNode<T>* queueBack;   
      int queueSize;         
};
//析构函数 
template<class T>
linkedQueue<T>::~linkedQueue()
{
   while (queueFront != NULL)
   {
      chainNode<T>* nextNode = queueFront->next;
      delete queueFront;
      queueFront = nextNode;
   }
}
//删除队首 
template<class T>
void linkedQueue<T>::pop()
{
   if (queueFront == NULL)
      exit(1);
   chainNode<T>* nextNode = queueFront->next;
   delete queueFront;
   queueFront = nextNode;
   queueSize--;
}
template<class T>
void linkedQueue<T>::push(const T& theElement)
{
   chainNode<T>* newNode = new chainNode<T>(theElement, NULL);
   if (queueSize == 0)
      queueFront = newNode;      
   else 
      queueBack->next = newNode;  
   queueBack = newNode;

   queueSize++;
}
class minHeap{
	public:
	minHeap() { length = 0; p = new HuffmanNode*[26]; }
	//because there are 26 words in the alphabet
	~minHeap() { delete[]p; }
	void initialize(HuffmanNode** a, int n);
	void insert(HuffmanNode* num);
	void pop();
	HuffmanNode* top() { return p[1];}
	private:
		int length;
		HuffmanNode **p;
};
void minHeap::initialize(HuffmanNode **a, int n)//初始化
{
	length = n;
	for (int i = 0; i < n; i++)
		p[i + 1] = a[i];
	for (int root = length / 2; root >= 1; root--)
	{
		HuffmanNode* rootelement = p[root];
		int child = 2 * root;
		while (child <= length)
		{
			if (child<length&&p[child]->element>p[child + 1]->element)
			{
				child++;
			}
			if (rootelement->element <= p[child]->element)
				break;
			else
			{
				p[child / 2] = p[child];
				child = child * 2;
			}
		}
		p[child / 2] = rootelement;
	}
}
void minHeap::insert(HuffmanNode* num)//插入函数
{
	int current = length + 1;//元素将要插入的位置
	length++;
	while (current > 1 && p[current / 2]->element > num->element)
	{
		p[current] = p[current / 2];
		current = current / 2;
	}
	p[current] = num;
}
void minHeap::pop()//删除函数 
{
	HuffmanNode* lastelement = p[length];
	int root = 1;
	int child = 2;
	length--;
	while (child <= length)
	{
		if (child<length&&p[child]->element>p[child + 1]->element)
		{
			child++;
		}
		if (lastelement->element <= p[child]->element)
			break;
		p[root] = p[child];
		root = child;
		child = child * 2;
	}
	p[root] = lastelement;
}
class Huffmantree
{
	public:
		HuffmanNode *root;//定义根
		Huffmantree() {}//构造函数 
		~Huffmantree();//析构函数 
		void maketree(int *a,int n);//n为字符串的size
		void length();//霍夫曼编码长度
	private:
		int size; 
};
//析构函数 
Huffmantree::~Huffmantree(){
	linkedQueue<HuffmanNode*> q;
	q.push(root);
	for (int i = 0; i < size; i++)
	{
		HuffmanNode* currentNode = q.front();
		q.pop();
		if (currentNode->leftChild != NULL)
		{
			q.push(currentNode->leftChild);
		}
		if (currentNode->rightChild != NULL)
		{
			q.push(currentNode->rightChild);
		}
		delete currentNode;
	}
}
//建立一棵霍夫曼树 
void Huffmantree::maketree(int *a, int n)
{
	HuffmanNode **hufnode = new HuffmanNode*[n];
	for (int i = 0; i < n; i++)//置空 
	{
		hufnode[i] = new HuffmanNode();
		hufnode[i]->element = a[i];
		hufnode[i]->leftChild = hufnode[i]->rightChild = NULL;
	}
	minHeap h;
	h.initialize(hufnode, n);
	HuffmanNode *w, *x, *y;
	for (int i = 1; i < n; i++)//建立一棵霍夫曼树 
	{
		x = h.top(); h.pop();
		y = h.top(); h.pop();
		w = new HuffmanNode();
		w->leftChild = x;
		w->rightChild = y;
		w->element = x->element + y->element;
		x = NULL;
		y = NULL;
		h.insert(w);
	}
	size = n;
	root = h.top();
	h.pop();
}
//计算霍夫曼编码的长度
void Huffmantree::length()
{
	int result = 0;
	linkedQueue<HuffmanNode*> que;
	HuffmanNode *currentNode;
	que.push(root);
	root->weight = 0;
	while (!que.empty())
	{
		currentNode = que.front();
		que.pop();
		if (currentNode->leftChild != NULL)
		{
			que.push(currentNode->leftChild);
			currentNode->leftChild->weight = currentNode->weight + 1;
		}
		if (currentNode->rightChild != NULL)
		{
			que.push(currentNode->rightChild);
			currentNode->rightChild->weight = currentNode->weight + 1;
		}
		if (currentNode->leftChild == NULL && currentNode->rightChild == NULL)
		{
			result = result + currentNode->weight*currentNode->element;
		}
	}
	cout << result;
}
int main()
{
	string str;int index = 0,n= 0;
	cin>>str;
	int *a = new int[26];//统计各个字母出现频率 
	for (int i = 0; i < 26; i++)
		a[i] = 0;
	for (int j = 0; j < str.size(); j++)
	{
		a[(int)str[j] - 97]++;
		if (a[(int)str[j] - 97] == 1)
			n++;
	}
	int *b = new int[n];
	for (int k = 0;k < 26; k++)
	{
		if (a[k] != 0)
		{
			b[index]=a[k];
			index++;
		}
	}
	Huffmantree Huff;
	Huff.maketree(b,n);
	Huff.length();
	return 0;
}
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值