C ++ Blue Bridge Cup Basic Practice Huffuman Tree HERODING's Blue Bridge Cup Road

Resource limit
Time limit: 1.0s Memory limit: 512.0MB
Problem description
  Huffman tree has a wide range of applications in coding. Here, we only care about the construction process of Huffman tree.
  Given a list of numbers {pi} = {p0, p1,…, pn-1}, the process of constructing a Huffman tree with this list of numbers is as follows:
  1. Find the two smallest numbers in {pi}, set to pa and pb, Remove pa and pb from {pi}, then add their sum to {pi}. The cost of this process is recorded as pa + pb.
  2. Repeat step 1 until there is only one number left in {pi}.
  In the above operation process, all costs are added together to obtain the total cost of constructing the Huffman tree.
  Task for this problem: For a given sequence, please find the total cost of constructing a Huffman tree with that sequence.

For example, for the sequence {pi} = {5, 3, 8, 2, 9}, the construction process of the Huffman tree is as follows:
  1. Find the smallest two numbers in {5, 3, 8, 2, 9}, which are 2 and 3, delete them from {pi} and add 5 to get {5, 8, 9, 5}, the cost is 5.
  2. Find the smallest two numbers in {5, 8, 9, 5}, 5 and 5, remove them from {pi} and add 10 to get {8, 9, 10}, the cost is 10 .
  3. Find the smallest two numbers in {8, 9, 10}, which are 8 and 9, delete them from {pi} and add 17 to get {10, 17}, the cost is 17.
  4. Find the two smallest numbers in {10, 17}, which are 10 and 17, remove them from {pi} and add 27 to get {27}, the cost is 27.
  5. Now, there is only one number 27 left in the sequence. The construction process ends, and the total cost is 5 + 10 + 17 + 27 = 59.
Input format
  The first line of input contains a positive integer n (n <= 100).
  Next are n positive integers, representing p0, p1,…, pn-1, each number not exceeding 1000.
Output format
  Output the total cost of constructing the Huffman tree using these numbers.
Sample input
5
5 3 8 2 9
Sample output
59

Problem-solving ideas:
Huffman tree is a relatively classic algorithm, and its application scenarios are quite successful in cracking passwords and encryption. Today's question is actually very simple. After getting the smallest two numbers each time with the greedy idea, and then put it back into the array of the tree, and so on, until there is only one element in the array, output the cost of the construction process. Here I use two methods for everyone to answer.
The first method: the minimum heap, friends who have learned the data structure know that the process of writing the minimum heap is so difficult, but it must be said that it is really fragrant. Put all the input numbers into the minimum heap first Each time the top element of the heap is obtained from the smallest heap, it must be the minimum value, and so on, until there is only one element in the heap.
The second method: use the sort () function to sort, take the smallest element every time, pay attention to delete the extra elements.

There are two methods:

#include<bits/stdc++.h>

using namespace std;

template<class T>
class MinHeap {
private:
	T *heapArray;			// 存放堆数据的数组
	int CurrentSize;			// 当前堆中元素数目
	int MaxSize;			// 堆所能容纳的最大元素数目
public:
	MinHeap(const int n);			// 构造函数,n表示 堆的最大元素数目
	virtual ~MinHeap() { delete[]heapArray; }	// 析构函数
	void swap(int pos_x, int pos_y);	// 交换位置x和y的元素
	void BuildHeap();			// 建堆
	bool isEmpty();			// 如果堆空,则返回真
	bool isLeaf(int pos) const;	    		// 如果是叶结点,返回TRUE
	int leftchild(int pos) const;	   		// 返回左孩子位置
	int rightchild(int pos) const;		// 返回右孩子位置
	int parent(int pos) const;			// 返回父结点位置
	bool Remove(int pos, T& node); 		// 删除给定下标的元素
	bool Insert(const T& newNode);		// 向堆中插入新元素newNode
	T& RemoveMin();			// 从堆顶删除最小值
	void SiftUp(int position);		 // 从position向上开始调整,使序列成为堆
	void SiftDown(int left);         	// 向下筛选,参数left表示开始处理的数组下标
	void show();
	int getCurrentSize();
};

template<class T>
int MinHeap<T>::getCurrentSize() {
	return CurrentSize;
}


template<class T>
bool MinHeap<T>::isEmpty() {
	if (CurrentSize == 0) {
		return true;
	}
	else return false;
}

template<class T>
bool MinHeap<T>::isLeaf(int pos) const {
	if (pos % 2 == 1) {
		return true;
	}
	else return false;
}

template<class T>
void MinHeap<T>::swap(int pos_x, int pos_y) {
	T data = heapArray[pos_x];
	heapArray[pos_x] = heapArray[pos_y];
	heapArray[pos_y] = data;
}

template<class T>
void MinHeap<T>::BuildHeap() {
	for (int i = CurrentSize / 2 - 1; i >= 0; i--)// 反复调用筛选函数
		SiftDown(i);
}


template<class T>
MinHeap<T>::MinHeap(const int n) {
	if (n <= 0)     return;
	CurrentSize = 0;
	MaxSize = n;				// 初始化堆容量为n
	heapArray = new T[MaxSize];		// 创建堆空间
	BuildHeap();  // 此处进行堆元素的赋值工作
}

template<class T>
int MinHeap<T>::leftchild(int pos) const {
	return 2 * pos + 1;					 	// 返回左孩子位置
}

template<class T>
int MinHeap<T>::rightchild(int pos) const {
	return 2 * pos + 2;					   	// 返回右孩子位置
}
template<class T>
int MinHeap<T>::parent(int pos) const {
	return (pos - 1) / 2;				   		// 返回父结点位置
}

template <class T>
bool MinHeap<T>::Insert(const T& newNode) { // 向堆中插入新元素newNode
	if (CurrentSize == MaxSize)	return false; // 堆空间已经满
	heapArray[CurrentSize] = newNode;
	SiftUp(CurrentSize);					// 向上调整
	CurrentSize++;
	return true;
}

template<class T>
T& MinHeap<T>::RemoveMin() {	// 从堆顶删除最小值
	if (CurrentSize == 0) {
		cout << "Can't Delete";		// 调用RemoveMin之前,需要判断堆非空
		exit(1);
	}
	else {
		swap(0, --CurrentSize);	                 // 交换堆顶和最后一个元素
		if (CurrentSize > 1) {
			SiftDown(0);   // 从堆顶开始筛选
		}
		return heapArray[CurrentSize];
	}
}
template<class T>
bool MinHeap<T>::Remove(int pos, T& node) {   	// 删除给定下标的元素
	if ((pos < 0) || (pos >= CurrentSize))     return false;
	node = heapArray[pos];
	heapArray[pos] = heapArray[--CurrentSize];	// 用最后的元素值替代删除位置的元素
	if (heapArray[parent(pos)] > heapArray[pos])
		SiftUp(pos);			// 当前元素小于父结点,需要上升调整
	else SiftDown(pos);			// 当前元素大于父结点,向下筛
	return true;
}

template<class T>
void MinHeap<T>::SiftUp(int position) {
	// 从position向上开始调整
	int temppos = position;
	T temp = heapArray[temppos];
	while ((temppos > 0) && (heapArray[parent(temppos)] > temp)) {
		heapArray[temppos] = heapArray[parent(temppos)];
		temppos = parent(temppos);
	}
	heapArray[temppos] = temp;
}

template <class T>
void MinHeap<T>::SiftDown(int left) {
	int i = left;			// 标识父结点
	int j = leftchild(i); 			// 标识关键值较小的子结点
	T temp = heapArray[i];		// 保存父结点
	while (j < CurrentSize) {       		// 过筛
		if ((j < CurrentSize - 1) && (heapArray[j] > heapArray[j + 1]))
			//若有右子节点,且小于左子节点
			j++;							// j指向右子结点
		if (temp > heapArray[j]) {  //若父节点大于子节点的值则交换位置
			heapArray[i] = heapArray[j];
			i = j;
			j = leftchild(j);
		}
		else break;  //堆序满足,跳出
	}
	heapArray[i] = temp;
}

template<class T>
void MinHeap<T>::show() {
	for (int i = 0;i < CurrentSize; i++)
	{
		cout << heapArray[i] << " ";
	}
}
int main() {
	MinHeap<int> heap(100);
	int i, n;
	cin >> n; 
	for(i = 0; i < n; i++) {
		int data;
		cin >> data;
		heap.Insert(data);
	}
	int sum = 0;
	int num = 0;
	while(heap.getCurrentSize() > 1){
		num += heap.RemoveMin();
		num += heap.RemoveMin();
		sum += num;
		heap.Insert(num);
		num = 0;
	} 
	cout << sum;
	return 0;
}
#include<bits/stdc++.h>

using namespace std;

int main()
{
    int a[100];
    int i,n;
    cin >> n;
    for(i = 0; i < n; i++) {
    	cin >> a[i];
	}
    sort(a,a+n);//从小到大排序
    int sum = 0;
    while(n > 1)
    {
        i=0;
        a[i] = a[i] + a[i+1];
        sum += a[i];
        a[i + 1] = -1;//将这个数去除
        sort(a,a+n);
        for(i = 0;i < n-1; i++)//把-1值覆盖 
            a[i] = a[i+1];
    n--;
}
    cout << sum;
    return 0;
}

Published 7 original articles · won 8 · views 804

Guess you like

Origin blog.csdn.net/HERODING23/article/details/105673503