问题描述
分析
做了,在POJ上能AC,但是在coursera上一直提示Compile Error. 没找着问题,呃,,,
源码
#include<iostream>
using namespace std;
template <class T>
class BinaryTreeNode
{
private:
T element; //二叉树结点数据域
BinaryTreeNode<T>* left; //二叉树结点指向左子树的指针
BinaryTreeNode<T>* right; //二叉树结点指向左子树的指针
public:
BinaryTreeNode();
BinaryTreeNode(const T& ele); //给定数据的构造函数
BinaryTreeNode(const T& ele,BinaryTreeNode* l, BinaryTreeNode* r);//给定数据的左右指针的构造函数
T value() const; //返回当前结点的数据
BinaryTreeNode<T>& operator= (BinaryTreeNode<T>& Node)
{this->element=Node.element; this->left=Node.left; this->right=Node.right;
return *this;}; //重载赋值操作符
bool operator> (BinaryTreeNode<T>& Node)
{return this->element>Node.element;}; //重载>操作符
bool operator< (BinaryTreeNode<T>& Node)
{return this->element<Node.element;}; //重载<操作符
BinaryTreeNode<T>* leftchild() const; //返回当前结点指向左子树的指针
BinaryTreeNode<T>* rightchild() const; //返回当前结点指向右子树的指针
void setLeftchild(BinaryTreeNode<T>*); //设置当前结点的左子树
void setRightchild(BinaryTreeNode<T>*); //设置当前结点的右子树
void setValue(const T& val); //设置当前结点的数据域
bool isLeaf() const; //判定当前结点是否为叶结点,若是返回true
};
template <class T>
class MinHeap
{
private:
T* heapArray; //存放堆数据的数组
int CurrentSize; //当前堆中的元素数目
int MaxSize; //最大元素数目
public:
MinHeap(const int n); //构造函数,参数n为堆的最大元素数目
virtual ~MinHeap() {delete []heapArray;}; //析构函数
bool isLeaf(int pos) const; //判断是否为叶节点
int leftchild(int pos) const; //返回左孩子位置
int rightchild(int pos) const; //返回右孩子位置
int parent(int pos) const; //返回父结点位置
bool Remove(int pos, T& node); //删除给定下标的元素, 返回其元素的值
bool RemoveMin(T& node); //从堆顶删除最小值
bool Insert(T& newNode); //向堆中插入新元素
void SiftDown(int left); //从left开始向下筛选
void SiftUp(int position); //从position向上开始调整,使序列成为堆
};
template <class T>
class HuffmanTree
{
private:
BinaryTreeNode<T>* root; //Huffman树的树根
BinaryTreeNode<T>* nodeArray; //用于保存树的每一个结点
void MergeTree(BinaryTreeNode<T> &ht1,BinaryTreeNode<T> &ht2, BinaryTreeNode<T>* parent); //把ht1和ht2为根的Huffman子树合并成一棵以parent为根的二叉树
int wep; //带权外部路径长度
public:
HuffmanTree(T weight[],int n); //构造Huffman树,weight是存储权值的数组,n是数组长度
~HuffmanTree(); //析构函数
void traverseNode(BinaryTreeNode<T>* node, int length);
int weightedExternalPath();
};
int main() {
int n;
cin >> n;
int weight[100]={0};
for(int i=0; i<n; i++) {
cin >> weight[i];
}
HuffmanTree<int> ht(weight, n);
cout << ht.weightedExternalPath() << endl;
return 0;
}
/***************************BinaryTreeNode***************************************/
template<class T>
BinaryTreeNode<T>::BinaryTreeNode()
{
left=right=NULL;
}
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& ele) //给定数据的构造函数
{
element=ele;
left=right=NULL;
}
template<class T>
BinaryTreeNode<T>::BinaryTreeNode(const T& ele,BinaryTreeNode* l, BinaryTreeNode* r)
//给定数据的左右指针的构造函数
{
element=ele;
left=l;
right=r;
}
template<class T>
T BinaryTreeNode<T>::value() const
{
return element;
}
template<class T>
BinaryTreeNode<T>* BinaryTreeNode<T>::leftchild() const
{
return left; //返回当前结点指向左子树的指针
}
template<class T>
BinaryTreeNode<T>* BinaryTreeNode<T>::rightchild() const
{
return right; //返回当前结点指向右子树的指针
}
template<class T>
void BinaryTreeNode<T>::setLeftchild(BinaryTreeNode<T>* subroot)//设置当前结点的左子树
{
left=subroot;
}
template<class T>
void BinaryTreeNode<T>::setRightchild(BinaryTreeNode<T>* subroot)//设置当前结点的右子树
{
right=subroot;
}
template<class T>
void BinaryTreeNode<T>::setValue(const T& val) //设置当前结点的数据域
{
element = val;
}
template<class T>
bool BinaryTreeNode<T>::isLeaf() const //判定当前结点是否为叶结点,若是返回true
{
return (left == NULL) && (right == NULL);
}
/**********************MinHeap实现***************************/
template<class T>
MinHeap<T>::MinHeap(const int n)
{
if(n<=0)
return;
CurrentSize=0;
MaxSize=n;
heapArray=new T[MaxSize]; //创建堆空间
}
template<class T>
bool MinHeap<T>::isLeaf(int pos) const
{
return (pos>=CurrentSize/2)&&(pos<CurrentSize);
}
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>
void MinHeap<T>::SiftDown(int left)
{
int i=left; //标识父结点
int j=2*i+1; //标识关键值较小的子结点
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=2*j+1;
}
else break;
}
heapArray[i]=temp;
}
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>
bool MinHeap<T>::Remove(int pos, T& node) // 删除给定下标的元素, 返回其元素的值
{
if((pos<0)||(pos>=CurrentSize))
return false;
T temp=heapArray[pos];
heapArray[pos]=heapArray[--CurrentSize]; //用最后的元素代替被删除的元素
if (pos>0 && (heapArray[parent(pos)] > heapArray[pos]))
SiftUp(pos); //上升筛
else SiftDown(pos); //向下筛
node=temp;
return true;
}
template<class T>
bool MinHeap<T>::RemoveMin(T& node)
{
if(CurrentSize==0){
return false;
}
else{
node = heapArray[0];
heapArray[0]=heapArray[--CurrentSize]; //用最后的元素代替被删除的元素
if (CurrentSize>1) {
SiftDown(0);
}
return true;
}
}
template<class T>
bool MinHeap<T>::Insert(T& newNode)
{//向堆中插入一个结点
if(CurrentSize>=MaxSize)
return false;
heapArray[CurrentSize]=newNode;
SiftUp(CurrentSize);
CurrentSize++;
return true;
}
/**********************Huffman实现***************************/
template <class T>
void HuffmanTree<T>::MergeTree(BinaryTreeNode<T> &ht1,BinaryTreeNode<T> &ht2, BinaryTreeNode<T>* parent)
{
parent->setLeftchild(&ht1);
parent->setRightchild(&ht2);
parent->setValue(ht1.value()+ht2.value());
}
template <class T>
HuffmanTree<T>::HuffmanTree(T weight[],int n):wep(0)
{
nodeArray = new BinaryTreeNode<T>[2*n];
MinHeap<BinaryTreeNode<T>> heap(n); //定义最小值堆
BinaryTreeNode<T> NodeList;
for(int i=0;i<n;i++) //初始化
{
BinaryTreeNode<T> NodeList(weight[i]);
heap.Insert(NodeList); //向堆中添加元素
}
int j=0;
for(int i=0;i<n-1;i++)
//通过n-1次合并建立Huffman树
{
BinaryTreeNode<T>* parent;
parent=new BinaryTreeNode<T>;
heap.RemoveMin(nodeArray[j++]); //选择权值最小的结点
heap.RemoveMin(nodeArray[j++]); //选择权值次小的结点
MergeTree(nodeArray[j-2],nodeArray[j-1],parent); //合并权值最小的两棵树
heap.Insert(*parent); //把parent插入到堆中去
root=parent; //建立根结点
}
}
template <class T>
HuffmanTree<T>::~HuffmanTree()
{
delete [] nodeArray;
}
template <class T>
void HuffmanTree<T>::traverseNode(BinaryTreeNode<T>* node, int length)
{
if (node != NULL)
{
if (node->leftchild()==NULL && node->rightchild()==NULL)
{
wep += node->value()*length;
}
else {
traverseNode(node->leftchild(), length+1); //访问左子树
traverseNode(node->rightchild(), length+1); //访问右子树
}
}
}
template <class T>
int HuffmanTree<T>::weightedExternalPath()
{
traverseNode(root, 0);
return wep;
}