数据结构C++版 王红梅 OJ习题

1023: haffman编码

Description

根据权值序列构造huffman树,并输出各个权值对应的huffman编码,并计算wpl值。

已知部分代码如下:

#include <iostream>
#include <climits>   //INT_MAX
#include <string>
using namespace std;

template <class T>

//链式栈
struct Node
{
    T data;
    Node<T> *next; 
};

template <class T>
class LinkStack
{
public:
    LinkStack( );              //构造函数,置空链栈
    ~LinkStack( );             //析构函数,释放链栈中各结点的存储空间
    void Push(T x);           //将元素x入栈
    T Pop( );                  //将栈顶元素出栈
    T GetTop( );               //取栈顶元素(并不删除)
    bool Empty( );             //判断链栈是否为空栈
    void VisitStack();         //遍历栈(从顶到底)
private:
    Node<T> *top;             //栈顶指针即链栈的头指针
};

/*
 * 前置条件:栈不存在
 * 输    入:无
 * 功    能:栈的初始化
 * 输    出:无
 * 后置条件:构造一个空栈
 */

template <class T>
LinkStack<T>::LinkStack( )
{
 top=NULL;
}
/*
 * 前置条件:栈已存在
 * 输    入:无
 * 功    能:销毁栈
 * 输    出:无
 * 后置条件:释放栈所占用的存储空间
 */
template <class T>
LinkStack<T>::~LinkStack( )
{
 while (top)
 {
  Node<T> *p;
  p=top->next;
        delete top;
        top=p;
 }
}

/*
 * 前置条件:栈已存在
 * 输    入:节点s
 * 功    能:在栈顶插入该节点
 * 输    出:无
 * 后置条件:如果插入成功,栈顶增加了一个元素
 */

template<class T>
void LinkStack<T>::Push(T x)
{
    Node<T> *s;
 s=new Node<T>; 
 if(!s) throw"Overflow";
    s->data = x;     //申请一个数据域为x的结点s
    s->next = top;
 top=s;           //将结点s插在栈顶
}

/*
 * 前置条件:栈已存在
 * 输    入:无
 * 功    能:删除栈顶元素
 * 输    出:如果删除成功,返回被删元素值,否则,抛出异常
 * 后置条件:如果删除成功,栈顶减少了一个元素
 */   

template <class T> T LinkStack<T>::Pop( )
{  
    Node<T> *p;
 int x;
    if (top==NULL) throw "Downflow";
    x=top->data;            //暂存栈顶元素
    p=top;
 top=top->next;         //将栈顶结点摘链
    delete p;
    return x;
}

/*
 * 前置条件:栈已存在
 * 输    入:无
 * 功    能:读取当前的栈顶元素
 * 输    出:若栈不空,返回当前的栈顶元素值
 * 后置条件:栈不变
 */

template <class T>
T LinkStack<T>::GetTop( )
{
    if (top)
  return top->data;
 else throw"Downflow";
}

/*
 * 前置条件:栈已存在
 * 输    入:无
 * 功    能:判断栈是否为空
 * 输    出:如果栈为空,返回1,否则,返回0
 * 后置条件:栈不变
 */

template <class T>
bool LinkStack<T>::Empty( )
{
    return top==NULL;
}
template <class T>
void  LinkStack<T>::VisitStack()
{
       Node<T> *p;;
       for(p=top;p;p=p->next)
           cout<<p->data;
}

//huffman树
const int MaxSize=100;

//huffman树结点信息(注意增加了各个权值所对应的汉字信息)
struct HuffNode{
 int weight;   //权值
 string word;  //权值对应的信息
 int parent;   //双亲所在数组下标
 int lchild,rchild;  //左右孩子所在数组下标
};

//huffman树类
class HuffTree
{
private:
 HuffNode hufftree[MaxSize+1];   //huffman树的存储(1~2*n-1下标)
 int n;  //权值个数
public:
    HuffTree(int w[],string str[],int n);   //initialize
 void SelectMinW(int n,int &min); //选择最小权值的根结点所在下标
 void VisitHuffTree();    //输出huffmantree
    int HuffCode(LinkStack<char> S[]);  //设计haffman编码并计算wpl值,栈S[1]~S[n]存储各个权值的编码
    void DisplayAllCoding(LinkStack<char> S[]); //输出各个权值的huffman编码
};
HuffTree::HuffTree(int w[],string str[],int n){
 int i,min1,min2;
 hufftree[0].weight=INT_MAX;
// hufftree[0].parent=-1;
 for(i=1;i<=n;i++){
  hufftree[i].weight=w[i];
  hufftree[i].word=str[i];
//  cout<<hufftree[i].word<<" ";
  hufftree[i].parent=-1;
  hufftree[i].lchild=-1;
  hufftree[i].rchild=-1;
 }
 for( ;i<=2*n-1;i++){
  SelectMinW(i,min1);
  SelectMinW(i,min2);
//  cout<<"select: "<<min1<<"\t"<<min2<<endl;
  hufftree[i].lchild=min1;
  hufftree[i].rchild=min2;
  hufftree[i].weight=hufftree[min1].weight+hufftree[min2].weight;
  hufftree[i].parent=-1;
  hufftree[min1].parent=i;
  hufftree[min2].parent=i;
 }
 this->n=n;
}

void HuffTree::SelectMinW(int n,int &min){
 min=0;
 for(int i=1;i<=n;i++)
  if(hufftree[i].parent==-1&&
      hufftree[i].weight<hufftree[min].weight) min=i;
 hufftree[min].parent=0;//避免下一次重复被选
}

void HuffTree::VisitHuffTree(){
 cout<<"No\tweight\tparent\tlchild\trchild\n";
 for(int i=1;i<=2*n-1;i++){
  cout<<i<<"\t"<<hufftree[i].weight<<"\t";
  cout<<hufftree[i].parent<<"\t";
  cout<<hufftree[i].lchild<<"\t"<<hufftree[i].rchild<<"\n";
 }
}
 
int main(){
 int w[MaxSize/2],n;//w存储权值,n存储权值个数   

string inf[MaxSize];//存储各个权值对应的信息(一个汉字)
    cin>>n;   //输入权值个数
 int i;
 for(i=1;i<=n;i++)
  cin>>w[i];   //输入权值
 for(i=1;i<=n;i++)
  cin>>inf[i];  //输入各个权值对应的汉字
 
 HuffTree ht(w,inf,n);   //create huffman tree
// ht.VisitHuffTree();     //display huffman tree

 LinkStack<char> S[100];   //storage huffman coding
 int wpl=ht.HuffCode(S);   //calculate the huffman coding for every weight and wpl
 ht.DisplayAllCoding(S);   //display huffman coding
 cout<<"WPL="<<wpl<<endl;  //display wpl
 return 0;
}

Input

输入格式:

权值个数

各个权值

各个权值对应的汉字信息

例如:

5
12 35 17 7 22
li zhao qian sun zhou

Output

Sample Input

5
12 35 17 7 22
li zhao qian sun zhou

Sample Output

Coding of 12(li):011
Coding of 35(zhao):11
Coding of 17(qian):00
Coding of 7(sun):010
Coding of 22(zhou):10
WPL=205
//
// Created by Legends丶Hu on 2020/2/5.
//
#include <iostream>
#include <climits>
using namespace std;

template<class T>
struct Node {
    T data;
    Node<T> *next;
};

template<class T>
class LinkStack {
public:
    LinkStack();              //构造函数,置空链栈
    ~LinkStack();             //析构函数,释放链栈中各结点的存储空间
    void Push(T x);           //将元素x入栈
    T Pop();                  //将栈顶元素出栈
    T GetTop();               //取栈顶元素(并不删除)
    bool Empty();             //判断链栈是否为空栈
    void Display();           //输出栈
private:
    Node<T> *top;             //栈顶指针即链栈的头指针
};


template<class T>
LinkStack<T>::LinkStack() {
    top = NULL;
}

template<class T>
LinkStack<T>::~LinkStack() {
    while (top) {
        Node<T> *p = top;
        top = top->next;
        delete p;
    }
}

template<class T>
void LinkStack<T>::Push(T x) {
    Node<T> *s = new Node<T>;
    s->data = x;
    s->next = top;
    top = s;
}

template<class T>
T LinkStack<T>::Pop() {
    if(top == NULL) throw "Downflow";
    T x = top->data;
    Node<T> *p = top;
    top = top->next;
    delete p;
    return x;
}

template<class T>
T LinkStack<T>::GetTop() {
    if (top == NULL) throw "Downflow";
    return top->data;
}

template<class T>
bool LinkStack<T>::Empty() {
    return top == NULL;
}


template<class T>
void LinkStack<T>::Display() {
    Node<T> *p = top;
    while (p) {
        cout << p->data;
        p = p->next;
    }
    cout << endl;
}

//huffman树
const int MaxSize = 100;
//huffman树结点信息(注意增加了各个权值所对应的汉字信息)
struct HuffNode {
    int weight;   //权值
    string word;  //权值对应的信息
    int parent;   //双亲所在数组下标
    int lchild, rchild;  //左右孩子所在数组下标
};

//huffman树类
class HuffTree {
private:
    HuffNode hufftree[MaxSize + 1];   //huffman树的存储(1~2*n-1下标)
    int n;  //权值个数
public:
    HuffTree(int w[], string str[], int n);   //initialize
    void SelectMinW(int n, int &min); //选择最小权值的根结点所在下标
    void VisitHuffTree();    //输出huffmantree
    int HuffCode(LinkStack<char> S[]);  //设计haffman编码并计算wpl值,栈S[1]~S[n]存储各个权值的编码
    void DisplayAllCoding(LinkStack<char> S[]); //输出各个权值的huffman编码
};

HuffTree::HuffTree(int w[], string str[], int n) {
    int i, min1, min2;
    hufftree[0].weight = INT_MAX;
// hufftree[0].parent=-1;
    for (i = 1; i <= n; i++) {
        hufftree[i].weight = w[i];
        hufftree[i].word = str[i];
//  cout<<hufftree[i].word<<" ";
        hufftree[i].parent = -1;
        hufftree[i].lchild = -1;
        hufftree[i].rchild = -1;
    }
    for (; i <= 2 * n - 1; i++) {
        SelectMinW(i, min1);
        SelectMinW(i, min2);
//  cout<<"select: "<<min1<<"\t"<<min2<<endl;
        hufftree[i].lchild = min1;
        hufftree[i].rchild = min2;
        hufftree[i].weight = hufftree[min1].weight + hufftree[min2].weight;
        hufftree[i].parent = -1;
        hufftree[min1].parent = i;
        hufftree[min2].parent = i;
    }
    this->n = n;
}

void HuffTree::SelectMinW(int n, int &min) {
    min = 0;
    for (int i = 1; i <= n; i++)
        if (hufftree[i].parent == -1 &&
            hufftree[i].weight < hufftree[min].weight)
            min = i;
    hufftree[min].parent = 0;//避免下一次重复被选
}

void HuffTree::VisitHuffTree() {
    cout << "No\tweight\tparent\tlchild\trchild\n";
    for (int i = 1; i <= 2 * n - 1; i++) {
        cout << i << "\t" << hufftree[i].weight << "\t";
        cout << hufftree[i].parent << "\t";
        cout << hufftree[i].lchild << "\t" << hufftree[i].rchild << "\n";
    }
}

int HuffTree::HuffCode(LinkStack<char> *S) {
    int wpl = 0;
    for (int i = 1; i <= n; i++) {
        int t = hufftree[i].parent;
        int q = i;
        int val = 0;
        while (t != -1) {
            if (hufftree[t].rchild == q)
                S[i].Push('1');
            else if (hufftree[t].lchild == q)
                S[i].Push('0');
            val++;
            q = t;
            t = hufftree[t].parent;
        }
        wpl += val * hufftree[i].weight;
    }
    return wpl;
}

void HuffTree::DisplayAllCoding(LinkStack<char> *S) {
    for (int i = 1; i <= n; i++) {
        cout << "Coding of " << hufftree[i].weight << "(" << hufftree[i].word
             << "):";
        S[i].Display();
    }
}

int main() {
    int w[MaxSize / 2], n;//w存储权值,n存储权值个数
    string inf[MaxSize];//存储各个权值对应的信息(一个汉字)
    cin >> n;   //输入权值个数
    int i;
    for (i = 1; i <= n; i++)
        cin >> w[i];   //输入权值
    for (i = 1; i <= n; i++)
        cin >> inf[i];  //输入各个权值对应的汉字

    HuffTree ht(w, inf, n);   //create huffman tree
    //ht.VisitHuffTree();     //display huffman tree
    LinkStack<char> S[100];   //storage huffman coding
    int wpl = ht.HuffCode(S);   //calculate the huffman coding for every weight and wpl
    ht.DisplayAllCoding(S);   //display huffman coding
    cout << "WPL=" << wpl << endl;  //display wpl
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值