【C++データ構造】ハフマンツリーコード実装

15044 ワード

HuffeManTree.h
#pragma once
#include "Stack.h"  //       
#include "Stack.cpp"

template
class CTree {
public:
    CTree(void);

public:
    T data = NULL;
    int weight = 1;
    CTree* lNode = nullptr;
    CTree* rNode = nullptr;
    string code = "";
};

template
class CHuffemanTree
{
public:
    CHuffemanTree(void);
    ~CHuffemanTree(void);

private:
    CTree* head = nullptr;   //      
    CStack*> stack;  //          
    int TotalWeight = 0;    //   
    string encode = "";         //     
    CStack*> stack_tree; //            

private:
    int GetLength(void); //   Stack    
    void Sort(void);  //   
    void WriteToCode(string str); //         
    void EnCode(CTree* node, string code, int k); //   
    void Insert(T data); //     
    void CreateHuffemanTree(void); //   stack      
    void DeleteTree(CTree* node);

public:
    void CreateHuffemanTree(string str); //               
    int GetTotalWeight(void); //      
    string GetEnCode(void); //     
    string GetDeCode(string str);  //   
    void Display(void); //  
};

HuffeManTree.cpp
#include "HuffemanTree.h"

template<class T>
CTree::CTree()
{
}

template<class T>
CHuffemanTree::CHuffemanTree()
{
}

template<class T>
CHuffemanTree::~CHuffemanTree()
{
     DeleteTree(head);
}

template<class T>
int CHuffemanTree::GetLength(void)
{
    int s_length = stack.GetLength();
    int length = 0;
    for (int i = 0; i < s_length; i++) {
        CTree* node = stack.At(i);
        length += node->weight;
    }
    return length;
}

template<class T>
void CHuffemanTree::Sort(void)
{
    int s_length = stack.GetLength();

    for (int i = 0; i < s_length; i++) {
        for (int j = i + 1; j < s_length; j++) {
            if (stack.At(i)->weight < stack.At(j)->weight) {
                CTree* temp;
                temp = stack.At(i);
                stack.At(i) = stack.At(j);
                stack.At(j) = temp;
            }
        }
    }
}

template<class T>
void CHuffemanTree::WriteToCode(string str)
{
    for (int i = 0; i < str.length(); i++) {
        char c = str.at(i);
        for (int j = 0; j < stack_tree.GetLength(); j++) {
            CTree* node = stack_tree.At(j);
            if (c == node->data) {
                encode += node->code;
            }
        }
    }
}

template<class T>
void CHuffemanTree::EnCode(CTree* node, string code, int k)
{
    if (nullptr == node) {
        return;
    }
    node->code = code;
    if (nullptr != node->lNode) {
        EnCode(node->lNode, node->code + "0", k + 1);
    }
    if (nullptr != node->rNode) {
        EnCode(node->rNode, node->code + "1", k + 1);
    }
    if (NULL != node->data) {   
        node->code = code;
        TotalWeight += k * node->weight;
        stack_tree.Push(node);
    }
}

template<class T>
void CHuffemanTree::Insert(T data)
{
    for (int i = 0; i < stack.GetLength(); i++) {
        CTree* temp = stack.At(i);
        if (data == temp->data) {
            temp->weight++;
            return;
        }
    }

    CTree* node = new CTree;
    node->data = data;
    stack.Push(node);
}

template<class T>
void CHuffemanTree::CreateHuffemanTree(void)
{
    if (stack.GetLength() <= 0) {
        return;
    }

    if (stack.GetLength() == 1) {
        head = stack.At(0);
    }

    for (int i = 0; i < stack.GetLength() - 1;) {
        Sort();
        CTree* node1 = stack.Pop();
        CTree* node2 = stack.Pop();
        CTree* node = new CTree;
        node->lNode = node1;
        node->rNode = node2;
        node->weight = node1->weight + node2->weight;
        stack.Push(node);
        head = node;
    }
    EnCode(head, "", 0);
}

template<class T>
void CHuffemanTree::DeleteTree(CTree* node)
    {
        if (nullptr != node) {
            return;
        }
        DeleteTree(node->lNode);
        DeleteTree(node->rNode);
        delete node;
        node = nullptr;
    }

template<class T>
void CHuffemanTree::CreateHuffemanTree(string str)
{
    for (int i = 0; i < str.length(); i++) {
        Insert(str.at(i));
    }
    CreateHuffemanTree();
    WriteToCode(str);
}

template<class T>
int CHuffemanTree::GetTotalWeight(void)
{
    if (nullptr == head) {
        return 0;
    }
    return TotalWeight;
}

template<class T>
string CHuffemanTree::GetEnCode(void)
{
    if (nullptr == head) {
        return "";
    }
    return encode;
}

template<class T>
string CHuffemanTree::GetDeCode(string str)
{
    string result = "";
    string temp = "";
    for (int i = 0; i < str.length(); i++) {
        temp += str.at(i);
        for (int j = 0; j < stack_tree.GetLength(); j++) {
            CTree* node = stack_tree.At(j);
            if (temp == node->code) {
                result += node->data;
                temp = "";
            }
        }
    }
    return result;
}

template<class T>
void CHuffemanTree::Display(void)
{
    CStack*> st;
    CTree* node = head;

    while (nullptr != node) {
        if (NULL != node->data) {
            cout << "Data = " << node->data << " Weight = " << node->weight << " Code = " << node->code.c_str() << endl;
        }
        if (nullptr != node->rNode) {
            st.Push(node->rNode);
        }
        node = node->lNode;
        if (nullptr == node) {
            node = st.Pop();
        }
    }
}

main.cpp
void main() {
    CHuffemanTree ht;
    ht.CreateHuffemanTree("hello world");
    ht.Display();
    cout << "TotalWeight = " << ht.GetTotalWeight() << endl;
    cout << "EnCode = " << ht.GetEnCode() << endl;
    cout << "DeCode = " << ht.GetDeCode(ht.GetEnCode()) << endl;
    system("pause");
}