huffman编码实现

huffman编码,本程序思路完全是原创,与金典相比可能效率有差距,但毕竟是自己写出的,很有必要记下自己的第一思路
首先huffman编码用笔写写,一会就发现就是:所有节点按照权值由小到大排序,然后取出最小的两个节点,将权值最小的两个做二叉树的叶子节点,然后生成父节点,再把父节点存进去,以此循环直至只剩下一个节点,当然不用想了,这个节点就是head节点了。
于是立马想到queue来解决,由于涉及到排序,还是自己写个queue。
//定义队列中节点和queue基本操作

class Node
{
public:
    char data = '0';
    int i;//表示权值

    //为每个节点增加父节点,左0右1权值使用便能唯一确定二叉树
    int weight = -1;
    Node *parent = 0;
    Node *next = 0;
    //huffman树中的左右节点
    Node *l_son = 0, *r_son = 0;

    Node(int k) :i(k){ };
    Node(char c, int k) :data(c), i(k){};
};

//链表x形式实现队列
class My_queue
{
public:

    Node *head, *rear;
    int count = 0;

    My_queue()
    {
        head = 0;
        rear = 0;
    }
    //插入
    void push(Node *node);
    //取头结点,并且删除头结点
    Node* front()
    {

        Node *p = head;
        if (head->next != 0)
        {
            head = head->next;
        }
        else
            head = 0;
        count--;
        return p;
    }
    //删除队首元素
    void pop()
    {
        count--;
        Node *p = head;
        head = head->next;
        delete p;
    }
    int size()
    {
        return count;
    }

};


void My_queue::push(Node *node)
{
    count++;
    if (head == 0)//如果myqueue为空
    {
        head = node;
        rear = node;
        return;
    }

    //顺序插入
    Node *p, *q;//当前节点 
    p = head;
    q = head->next;
    while (1)
    {
        //插在头部
        if (node->i <= head->i)
        {
            head = node;
            head->next = p;
            q = 0;
            p = 0;
            return;
        }
        //插在尾部
        if (node->i > rear->i)
        {
            rear->next = node;
            rear = node;
            p = 0;
            q = 0;
            return;
        }
        if (node->i > p->i&&node->i <= q->i)
        {
            p->next = node;
            node->next = q;
            return;
        }

        p = p->next;
        q = q->next;
    }
}
// huffman.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include"My_queue.hpp"
using namespace std;

//前序遍历
void pre_order(Node *n)
{
    int c_weight[8];
    memset(c_weight, -1,8*sizeof(int));
    if (n != 0)
    {
        if (n->data != '0')//n为所要寻找的编码码字
        {
            cout << n->data << ":";
            for (int i = 0; i < 8; i++)
            {
                if (n->weight == -1)
                    break;
                c_weight[i] = n->weight;
                n = n->parent;
            }
            for (int i= 7; i >= 0; i--)
            {
                if (c_weight[i] != -1)
                    cout << c_weight[i];
            }
            cout << endl;
            return;
        }
        pre_order(n->l_son);
        pre_order(n->r_son);
    }
}

int main()
{
    //建立huffman tree,不同与二叉树,其是由下向上建立
    My_queue my_queue;
    for (int i = 0; i < 8; i++)
    {
        cout << "please enter the char of node\n";
        char c;
        cin >> c;
        cout << "please enter the value of this node\n";
        int k;
        cin >> k;
        Node *node = new Node(c,k);
        my_queue.push(node);
    }

    //Node* n1 = my_queue.front();

    //cout << n1->data << "\t" << n1->i << endl;

    //只剩最后一个元素时退出循环
    Node *n1 = 0, *n2 = 0;
    while (my_queue.size() > 1)
    {
        //从队列中取出最小的两个元素
        n1= my_queue.front();
        n1->weight = 0;
        n2 = my_queue.front();
        n2->weight = 1;
        //new 一个新节点,作为做小的两个节点的父节点,其权值为两个之和
        Node *n = new Node((n1->i)+(n2->i));
        //双向二叉树,子节点能访问父节点,父节点能访问子节点
        n1->parent = n;
        n2->parent = n;

        n->l_son = n1;
        n->r_son = n2;
        //将新节点再次插入到队列中去
        my_queue.push(n);
    }
    Node *head = my_queue.front();

    //前序遍历寻找到节点
    pre_order(head);
    return 0;
}
// huffman.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include"My_queue.hpp"
using namespace std;

//前序遍历
void pre_order(Node *n)
{
    int c_weight[8];
    memset(c_weight, -1,8*sizeof(int));
    if (n != 0)
    {
        if (n->data != '0')//n为所要寻找的编码码字
        {
            cout << n->data << ":";
            for (int i = 0; i < 8; i++)
            {
                if (n->weight == -1)
                    break;
                c_weight[i] = n->weight;
                n = n->parent;
            }
            for (int i= 7; i >= 0; i--)
            {
                if (c_weight[i] != -1)
                    cout << c_weight[i];
            }
            cout << endl;
            return;
        }
        pre_order(n->l_son);
        pre_order(n->r_son);
    }
}

int main()
{
    //建立huffman tree,不同与二叉树,其是由下向上建立
    My_queue my_queue;
    for (int i = 0; i < 8; i++)
    {
        cout << "please enter the char of node\n";
        char c;
        cin >> c;
        cout << "please enter the value of this node\n";
        int k;
        cin >> k;
        Node *node = new Node(c,k);
        my_queue.push(node);
    }

    //Node* n1 = my_queue.front();

    //cout << n1->data << "\t" << n1->i << endl;

    //只剩最后一个元素时退出循环
    Node *n1 = 0, *n2 = 0;
    while (my_queue.size() > 1)
    {
        //从队列中取出最小的两个元素
        n1= my_queue.front();
        n1->weight = 0;
        n2 = my_queue.front();
        n2->weight = 1;
        //new 一个新节点,作为做小的两个节点的父节点,其权值为两个之和
        Node *n = new Node((n1->i)+(n2->i));
        //双向二叉树,子节点能访问父节点,父节点能访问子节点
        n1->parent = n;
        n2->parent = n;

        n->l_son = n1;
        n->r_son = n2;
        //将新节点再次插入到队列中去
        my_queue.push(n);
    }
    Node *head = my_queue.front();

    //前序遍历寻找到节点
    pre_order(head);
    return 0;
}

//其实huffman树写出来并不难,但是这个编码问题真是想了半天,本来一直想从head节点向下递归进行编码,但是路径太复杂,所以就放弃了,最后想到何不从下往上访问父节点,最后找到head节点,这可是唯一路径,所以立马转变思路,最后终于弄出来,其中仍然存在很多问题,比如指针的删除,后续逐步优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值