霍夫曼压缩真的式一个非常经典又非常优雅的算法。不知道大家是否都会求霍夫曼树。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。如果清楚的话,建议先去看一下霍夫曼树。他的原理是,将数据从小到大排序,将最小的两个生成一棵树,其权为二者的和。然后将其加入到队列中与其他的比较并继续此过程。 然后我们可以根据生成的树来获取前缀码。 然后用这些代码代替原本的数据。
class huffman
{
private:
const static int r = 256;
int freq[256] = {};
std::string st[256];
struct node
{
int index;
int times;
node *right;
node *left;
node()
{
};
node(int a, int b, node *r, node *l)
{
index = a;
times = b;
right = r;
left = l;
}
};
node *create_node(int a, int b, node *r, node *l)
{
node *newnode = new node;
newnode->index = a;
newnode->times = b;
newnode->right = r;
newnode->left = l;
return newnode;
}
node *x, *y,*p;
static bool comp(node a, node b)
{
return a.times > b.times;
}
node built_tire()
{
std::vector<node> pq;
for (int i = 0; i < r; i++)
{
if (freq[i] > 0)
{
node newnode(i,freq[i],nullptr,nullptr);
pq.push_back(newnode);
}
}
std::sort(pq.begin(), pq.end(), comp);
while (pq.size()>1)
{
x = &pq.back();
pq.pop_back();
y = &pq.back();
pq.pop_back();
p = create_node(0, x->times + y->times, x, y);
pq.push_back(*p);
std::sort(pq.begin(), pq.end(), comp);
}
return pq.back();
}
void built_code(node x, std::string s)
{
if (x.left == nullptr&&x.right == nullptr)
{
st[x.index] = s;
std::cout << x.index << std::endl;
return;
}
built_code( *x.left, s + '0');
built_code( *x.right, s + '1');
}
public:
void compress(std::string s)
{
for (int i = 0; i < s.length(); i++)
{
freq[s[i]]++;
}
std::vector<node> pq;
for (int i = 0; i < r; i++)
{
if (freq[i] > 0)
{
node newnode(i, freq[i], nullptr, nullptr);
pq.push_back(newnode);
}
}
std::sort(pq.begin(), pq.end(), comp);
while (pq.size() > 1)
{
x = create_node(pq.back().index, pq.back().times, pq.back().left, pq.back().right);
pq.pop_back();
y = create_node(pq.back().index, pq.back().times, pq.back().left, pq.back().right);
pq.pop_back();
p=new node(0, x->times + y->times, x, y);
pq.push_back(*p);
std::sort(pq.begin(), pq.end(), comp);
}
node root = pq.back();
built_code(root,"");
std::cout << s << std::endl;
for (int i = 0; i < s.length(); i++)
{
std::string code = st[s[i]];
std::cout << code;
}
}
};
文本
- destructors of objects with static storage duration are called in reverse order of completion of their constructors or the completion of their dynamic initialization, and the functions passed to std::atexit are called in reverse order they are registered (last one first).
a) any static objects whose initialization was completed before the call to std::atexit for some function F will be destroyed after the call to F during program termination. b) any static objects whose construction began after the call to std::atexit for some function F will be destroyed before the call to F during program termination (this includes the case where std::atexit was called from the constructor of the static object)
P.S.上述文字出自C++reference。
运行结果
看在孩子今天敲代码敲了四个多小时到23.26的面子上,给个赞吧
|