1.一些概念:
伪代码:
//动态
struct node{
int data;
node*l,node*r;
};
//静态
struct node{
int data;
int l,r;
}t[N];
一些性质:
对于第i个元素:(对于满二叉树)
左节点:2*i+1;
右节点:2*i+2;
父节点:(i-1)/2
2.二叉树的遍历
2.1BFS
2.2DFS
三种方式:
伪代码:
//先序
void traversal(node*node1){
cout<<node1->data;
traversal(node1->l);
traversal(node1->r);
}
//中序
void traversal(node*node1){
traversal(node1->l);
cout<<node1->data;
traversal(node1->r);
}
//后序
void traversal(node*node1){
traversal(node1->l);
traversal(node1->r);
cout<<node1->data;
}
3.哈夫曼树
首先先看一下什么事哈夫曼编码:
举个栗子
http://poj.org/problem?id=1521(北大poj平台)
题目简述:就是输入字符串,对每个字符串操作如下:然后分别用ASCII编码(每个字符为8位)和哈夫曼编码,输出ASCII码的长度和哈夫曼编码的长度,求出压缩比(保留1为小数,即使ASCII/哈夫曼),直到输入字符串END才结束
根据上面的论述,我们可以用优先队列去解决这个问题(因为要知道每个字符的多少,涉及到排序)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int main(){
priority_queue <int, vector<int>, greater<int> > q;
string s;
while(getline(cin, s) && s != "END"){
sort(s.begin(), s.end());
int num = 1; //一种字符出现的次数
for(int i = 1; i <= s.length(); i++){
if(s[i] != s[i-1]){ q.push(num); num = 1;}
else num++;
}
int ans = 0;
if(q.size() == 1) //题目的一个坑:只有一种字符的情况
ans = s.length();
while(q.size() > 1){ //最后一次合并不用加到ans里
int a = q.top(); q.pop(); //贪心:取出频次最少的两个
int b = q.top(); q.pop();
q.push(a+b); //把两个最小的合并成新的结点,重新放进队列
ans += a+b; //一种字符进几次队列,就累加几次。
//进一次队列,表示它在二叉树上深了一层,编码长度加1
}
q.pop();
printf("%d %d %.1f\n",s.length()*8,ans,(double)s.length()*8/(double)ans);
}
return 0;
}
问题:为什么 q.push(a+b); ans += a+b; 这一步什么意思?