哈夫曼树的实现
来源:互联网 发布:手机变脸软件 编辑:程序博客网 时间:2024/06/05 05:00
BinaryTree.h
#pragma once#pragma once #include<iostream> using namespace std; template<class T> struct BTNode { BTNode() { lchild = rchild = NULL; } BTNode(const T& x){ element = x; lchild = rchild = NULL; } BTNode(const T& x, BTNode<T>* l, BTNode<T>* r) { element = x; lchild = l; rchild = r; } T element; BTNode<T>* lchild, *rchild; }; template<class T> class BinaryTree { public: BinaryTree() { root = NULL; } ~BinaryTree(); bool IsEmpty()const; void Clear();//移去所有结点,使其成为空树 bool Root(T& x)const;//若二叉树非空,则x为根的值,并返回true,否则返回false void MakeTree(const T& x, BinaryTree<T>& left, BinaryTree<T>& right);//构造一棵二叉树,根的值为x,以left和right为左右子树 void BreakTree(T& x, BinaryTree<T>& left, BinaryTree<T>& right);//拆分二叉树为三部分,x为根的值,left和right分别为左右子树 //---------------------(华丽分割线)---------------------- void PreOrder(void (*Visit)(T& x));//使用函数Visit访问结点,先序遍历二叉树 void InOrder(void (*Visit)(T& x));//中序遍历二叉树 void PostOrder(void (*Visit)(T& x));//后序遍历二叉树 //---------------------(华丽分割线)---------------------- //分割线内的函数面向用户,主要提供一个用户与类内递归循环的一个接口 protected: BTNode<T>* root;//指向根结点的指针 private: void Clear(BTNode<T>* &t); //---------------------(华丽分割线)---------------------- void PreOrder(void (*Visit)(T& x),BTNode<T>*t); void InOrder(void (*Visit)(T& x), BTNode<T>*t); void PostOrder(void (*Visit)(T& x), BTNode<T>*t); //---------------------(华丽分割线)---------------------- //分割线内的函数才是主要实现递归遍历算法的函数 }; template<class T> BinaryTree<T>::~BinaryTree() { Clear(); }; template<class T> bool BinaryTree<T>::IsEmpty()const { return (root == NULL) ? true : false; }; template<class T> void BinaryTree<T>::Clear() { Clear(root); }; template<class T> void BinaryTree<T>::Clear(BTNode<T>*&t=root) { if (p!= NULL) { Clear(p->lchild); Clear(p->rchild); delete p; } }; template<class T> bool BinaryTree<T>::Root(T& x)const { if (root == NULL)return false; else { x = root.element; return true; } return false; }; template<class T> void BinaryTree<T>::MakeTree(const T& x, BinaryTree<T>& left, BinaryTree<T>& right) { if (root || &left == &right)return;//若root非空,说明root已是某二叉树树根 root = new BTNode<T>(x,left.root,right.root); left.root = right.root = NULL;//left和right已与新树结合,故将其指针设为空 }; template<class T> void BinaryTree<T>::BreakTree(T& x, BinaryTree<T>& left, BinaryTree<T>& right) { if (!root || &left == &right || left.root || right.root)return; //如果实参left和right的root非空则说明用户传过来用于获取左右子树的的BTNode指针是某个树的结点 x == root->element; left.root = root->lchild; right.root = root->rchild; delete root; root = NULL; }; //先序遍历,面向用户 template<class T> void BinaryTree<T>::PreOrder(void(*Visit)(T& x)) { PreOrder(Visit, root); }; //先序遍历,真正实现的函数 template<class T> void BinaryTree<T>::PreOrder(void(*Visit)(T& x), BTNode<T>* t) { if (t) { Visit(t->element); PreOrder(Visit, t->lchild); PreOrder(Visit, t->rchild); } }; template<class T> void Visit(T& x) { cout << x << " "; }; //中序遍历,面向用户 template<class T> void BinaryTree<T>::InOrder(void(*Visit)(T& x)) { InOrder(Visit, root); }; //中序遍历,真正实现的函数 template<class T> void BinaryTree<T>::InOrder(void(*Visit)(T& x),BTNode<T>*t) { if (t) { InOrder(Visit, t->lchild); Visit(t->element); InOrder(Visit, t->rchild); } }; //后序遍历,面向用户 template<class T> void BinaryTree<T>::PostOrder(void(*Visit)(T& x)) { InOrder(Visit, root); }; //后序遍历,真正实现的函数 template<class T> void BinaryTree<T>::PostOrder(void(*Visit)(T& x),BTNode<T>*t) { if (t) { PostOrder(Visit, t->lchild); PostOrder(Visit, t->rchild); Visit(t->element); } };PrioQueue.h
#pragma once/*优先权队列是多个元素的集合,每个元素都有一个优先权。优先权队列的特点是:每次从队列中取出具有最高优先权的元素ADT PrioQueue{Data:n个元素的最小堆Operation:Create();//建立一个空队列Destroy();//撤销一个队列IsEmpty();//空则返回true,非空则falseIsFull();//满则true,非满则falseAppend(x);//元素值为x的新元素入队Serve(x);//将该队列中具有最小优先权的元素值返回给x,并从优先权队列中删除该元素}*/template<class T>class PrioQueue{public:PrioQueue(int mSize = 20) {maxSize = mSize;q = new T[maxSize];}~PrioQueue() { delete[]q; }bool IsEmpty() const{return n == 0;}bool IsFull() {return n == maxSize;}void Append(const T&x);void Serve(T& x);private:void AdjustDown(int r, int j);void AdjustUp(int j);T*q;int n, maxSize;};template<class T>void PrioQueue<T>::AdjustDown(int r, int j){int child = 2*r + 1;//child定位到r的左子位置T temp = q[r];while (child <= j) {if ((child < j) && (q[child] > q[child + 1]))child++;//找到左右子中最小的那一个if (temp <= q[child])break;//如果temp比左右子最小的都小,说明符合向下调整的规则q[(child - 1) / 2] == q[child];//将该子值赋给其父结点child = 2 * child + 1;//继续向下(跳到该节点的子节点)}q[(child - 1) / 2] = temp;//temp的位置}template<class T>void PrioQueue<T>::AdjustUp(int j){//j为新插入元素的位置+1int i = j; T temp = q[i];while (i > 0 && temp < q[(i - 1) / 2]) {q[i] = q[(i - 1) / 2];//父子交换i = (i - 1) / 2;//跳到该节点的父位置}q[i] = temp;//i即为temp最后合理的位置}//因为插入新元素之前堆中元素都已经满足最小堆的条件//故只需调整新元素影响到的节点即可template<class T>void PrioQueue<T>::Append(const T&x) {if (IsFull())throw Overflow;q[n++] = x;//将新元素插入完全二叉树的最后位置AdjustUp(n - 1);//新元素插入位置即为n-1,故用AdjustUp调整0~n-1;}template<class T>void PrioQueue<T>::Serve(T& x) {if (IsEmpty())throw Underflow;x = q[0]; //返回具有最低优先权的元素(即堆顶元素)q[0] = q[--n];//然后将堆底元素放到堆顶AdjustDown(0, n - 1);//向下调整}
HfmTree.h
#pragma once#include"BinaryTree.h"#include"PrioQueue.h"template<class T>class HfmTree :public BinaryTree<T> {public :HfmTree<T>CreateHfmTree(T w[], int n);operator T()const { return weight; }T getW() { return weight; }void putW(const T& x) { weight = x; }//设置权重setNull() { root = NULL; }private:T weight;};template<class T>HfmTree<T> HfmTree<T>::CreateHfmTree(T w[], int n) {PrioQueue<HfmTree<T>>pq(n);//pq是一个优先权队列,他的元素是哈夫曼树对象HfmTree<T>x, y, z, zero;//----------------------第一个for循环--------------for (int i = 0; i < n; i++) {z.MakeTree(w[i], x, y);z.putW(w[i]);//构造一个数中只有一个结点的哈夫曼树对象pq.Append(z);//将哈夫曼树对象放进优先权队列z.setNull();//将z置为空数}//将w数组中的每一个元素当作一个哈夫曼树的权值构造一//个只有一个结点的哈夫曼树,pq//压进优先权队列pq//----------------------第一个for循环--------------//----------------------第二个for循环--------------for (int i = 1; i < n; i++) {pq.Serve(x);//取出最小值pq.Serve(y);//取出次最小值z.MakeTree(x.getW() + y.getW(), x, y);//分别将该次取出的最小值和次最小值当作左、右子//构造一个新的哈夫曼树对象z.putW(x.getW() + y.getW());pq.Append(z);z.setNull();}//对优先权队列pq中的元素(即哈夫曼树对象)进行合并n-1次//则最后剩一个完整的即构造完成的哈夫曼树//----------------------第二个for循环--------------pq.Serve(z);return z;}
0 0
- 哈夫曼树的实现
- 哈夫曼树的java实现
- 哈夫曼树的实现
- 哈夫曼树的代码实现
- 哈夫曼树的实现
- 哈夫曼树的实现
- 哈夫曼树的java实现
- 哈夫曼树的实现
- 哈夫曼树的编码实现
- 哈夫曼树的实现
- 哈夫曼树的c++实现
- 哈夫曼树的实现
- C++ 哈夫曼树的实现
- 哈夫曼树的实现
- 哈夫曼树的介绍 ---java实现
- 哈夫曼树的c语言实现
- 三子棋的实现的实现的实现
- 哈夫曼编码和哈夫曼树的实现——Pascal实现
- 71. Simplify Path
- emacs注释快捷键
- 四种C#实现播放声音的方法,如DirectX ,SoundPlayer, Windows Media Player
- pandas处理excel数据经验
- 从零开始学_JavaScript_系列(31)——事件代理/事件委托
- 哈夫曼树的实现
- MySQL 字符集与校对规则
- HDU 1269 迷宫城堡 (Tarjan 算法)
- 从此起飞~博客
- (一)开发环境搭建,基本语法,字符串,数组
- Acticle 6:javascript事件:事件的绑定
- 改良版进程管理
- deploy myeclipse j2ee project to server 按了没反应 怎么办
- document.ready和window.onload的区别