您的位置:首页 > 理论基础 > 数据结构算法

二叉树应用-Huffman编码树(数据结构基础 第6周)

2016-07-10 20:52 375 查看
问题描述



分析

做了,在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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: