哈夫曼树_1172

题目描述:

哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。

输入:

输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。

输出:

输出权值。

样例输入:
5  
1 2 2 5 9
样例输出:
37
 
 
// Huffman2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

typedef struct tagHuffmanNode
{
	int nWeight;	//当前节点的权值
	int nParent;	//父索引,便于从叶子到根得到Huffman编码
	int nLeft;		//左右孩子
	int nRight;

	struct tagHuffmanNode() : nWeight(0), nParent(0), nLeft(0), nRight(0){}
}HuffmanNode;

void CalcFrequency(const char* str, int* pWeight)
{
	while(*str)
	{
		pWeight[*str]++;
		str++;
	}
}

void CalcExistChar(int* pWeight, int N, vector<int>& pChar)
{
	int j = 0;
	for(int i = 0; i < N; i++)
	{
		if(pWeight[i] != 0)
		{
			pChar.push_back(i);
			if(j != i)
			{
				pWeight[j] = pWeight[i];
			}
			j++;
		}
	}
}

void SelectNode(const HuffmanNode* pHuffmanTree, int n, int& s1, int &s2)
{
	s1 = -1;	//无效值
	s2 = -1;
	int nMin1 = -1;	//无效值
	int nMin2 = -1;
	for(int i = 0; i < n; i++)
	{
		if((pHuffmanTree[i].nParent == 0) && (pHuffmanTree[i].nWeight > 0))
		{
			if((s1 < 0) || (nMin1 > pHuffmanTree[i].nWeight))
			{
				s2 = s1;
				nMin2 = nMin1;
				s1 = i;
				nMin1 = pHuffmanTree[s1].nWeight;
			}
			else if((s2 < 0) || (nMin2 > pHuffmanTree[i].nWeight))
			{
				s2 = i;
				nMin2 = pHuffmanTree[s2].nWeight;
			}
		}
	}
}

void HuffmanCoding(int *pWeight, int N, vector<vector<char> >& code) 
{ 
	if (N <= 0)
		return;
	int m = 2 * N - 1;	//N个结点的Huffman树需要2N-1个结点
	HuffmanNode* pHuffmanTree = new HuffmanNode[m];
	int s1, s2;

	int i;
	//建立叶子结点
	for (i = 0; i < N; i++) 
		pHuffmanTree[i].nWeight = pWeight[i];

	//每次选择权值最小的两个结点,建树
	for(i = N; i < m; i++)
	{ 
		SelectNode(pHuffmanTree, i, s1, s2);
		pHuffmanTree[s1].nParent = pHuffmanTree[s2].nParent = i;
		pHuffmanTree[i].nLeft = s1;
		pHuffmanTree[i].nRight = s2;
		pHuffmanTree[i].nWeight = pHuffmanTree[s1].nWeight + pHuffmanTree[s2].nWeight;
	}

	//根据建好的Huffman树从叶子到根计算每个叶结点的编码
	int node, nParent;
	for(i = 0; i < N; i++)
	{
		vector<char>& cur = code[i];
		node = i;
		nParent = pHuffmanTree[node].nParent;
		while(nParent != 0)
		{
			if(pHuffmanTree[nParent].nLeft == node)
				cur.push_back('0');
			else
				cur.push_back('1');

			node = nParent;
			nParent = pHuffmanTree[node].nParent;
		}
		reverse(cur.begin(), cur.end());
	}
}

void PrintCode(char c, vector<char>& code)
{
	cout << (int)c << "   " << c << ":   ";
	for(vector<char>::iterator it = code.begin(); it != code.end(); it++)
	{
		cout << *it;
	}
	cout << '\n';
}

void Print(vector<vector<char> >& code, vector<int>& pChar)
{
	int size = (int)code.size();
	for(int i = 0; i < size; i++)
	{
		PrintCode(pChar[i], code[i]);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	const int N = 256;
	char str[] = "when I was young I'd listen to the radio\
				waiting for my favorite songs\
				when they played I'd sing along,\
				it make me smile.\
				those were such happy times and not so long ago\
				how I wondered where they'd gone.\
				but they're back again just like a long lost friend\
				all the songs I love so well.\
				every shalala every wo'wo\
				still shines.\
				every shing-a-ling-a-ling \
				that they're starting\
				to sing so fine";
	int pWeight[N] = {0};
	CalcFrequency(str, pWeight);
	pWeight['\t'] = 0;
	vector<int> pChar;
	CalcExistChar(pWeight, N, pChar);
	int N2 = (int)pChar.size();
	vector<vector<char> > code(N2);
	HuffmanCoding(pWeight, N2, code);
	Print(code, pChar);
	return 0;
}
#include <iostream> 
#include <iomanip> 
#include <cmath> 
#include <string> 
#include <vector> 
#include <stack> 
#include <queue> 
#include <algorithm>
 #include <functional>
 using namespace std;   
int main() {  
   int n, m;     
while (cin >> n) {       
  priority_queue< int, vector<int>, greater<int> > Q;    
     for (int i = 0; i < n; ++i) {        
     cin >> m;     
        Q.push(m);      
   }        
   int sum = 0;      
   while (Q.size() > 1) {     
        int a = Q.top();       
      Q.pop();     
        int b = Q.top();          
   Q.pop();           
    sum += (a + b);  
           Q.push(a + b);     
    }         
  cout << sum << endl;     }     
 return 0; }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值