#include<iostream>
#include <limits.h>
#include<cstring>
using namespace std;
struct element{
int weight;
int lchild,rchild,parent;
};
void select(element huffTree[],int n, int &s1,int &s2){
s1 = s2 = 0;
int min1 = INT_MAX; //min1为最小值,INI_MAX数值为2^31-1
int min2 = INT_MAX; //min2为次小值
//找最小值就默认为最大值
for(int i=0;i<n;i++){
if(huffTree[i].parent == -1)
{ //筛选没有父节点的最小值和次小权值的下标
if(huffTree[i].weight < min1){
//如果权值比最小值小,更新最小值
min2 = min1;
s2 = s1; //次小值是之前的最小值
min1 = huffTree[i].weight;
s1 = i; //更新后的最小值
}else if((huffTree[i].weight >= min1)&& (huffTree[i].weight < min2)){
//如果权值大于等于最小值,小于次小值,更新次小值
min2 = huffTree[i].weight;
s2 = i;
}else{;}//如果大于次小值,则什么都不做
}
}
}
void HuffmanTree(element huffTree[],int w[],int n){
for(int i=0;i< 2*n-1;i++){ //初始化
huffTree[i].lchild = -1;
huffTree[i].rchild = -1;
huffTree[i].parent = -1;
}
for(int i = 0;i < n;i++){
huffTree[i].weight = w[i];
}
for(int k = n;k < 2 * n-1;k++){
int i1,i2; //下标i1对应的值最小,i2次小
select(huffTree,k,i1,i2) ;
huffTree[k].weight = huffTree[i1].weight+huffTree[i2].weight;
huffTree[i1].parent = k;
huffTree[i2].parent = k;
huffTree[k].lchild = i1;
huffTree[k].rchild = i2;
cout<<"最小下标:"<<i1 <<"次小下标:"<<i2<<endl;
}
}
void huffmanCoding(element * huffTree,char * huffCode[],int n){
char * temp = new char[n];//数组尽可能大,防止后面字符串赋值时溢出
temp [n-1] = '\0';
int start; //start是字符串temp的下标
int parent;
for(int i=0;i < n;i++){
start = n - 1;
//从后往前填写字符串,因为是从叶子节点向根节点遍历
int pos = i;
parent = huffTree[i].parent;
while(parent != -1){
if(huffTree[parent].lchild == pos){
temp[--start] = '0';
}else{
temp[--start] = '1';
}
pos = parent;
parent = huffTree[parent].parent;
}
huffCode[i] = new char[n-start];
strcpy(huffCode[i],&temp[start]);
//字符串拷贝,取temp[start]的地址及temp字符串首地址
}
delete temp;
}
int main(){
int n; //节点个数
cout << "请输入节点个数:"<<endl;
cin >> n;
int * w = new int[n];
cout << "请输入" << n << "个权值" <<endl;
for(int i=0;i<n;i++){
cin>>w[i];
}
element *huffTree = new element[2 * n - 1];
HuffmanTree(huffTree, w, n);
cout << "打印哈夫曼树的数组内容:"<<endl;
cout << "weight parent lchild rchild" << endl;
for (int i = 0; i < 2*n-1; i++) {
cout << huffTree[i].weight << " \t" << huffTree[i].parent << " \t"
<< huffTree[i].lchild << " \t" << huffTree[i].rchild << endl;
}
char **huffCode = new char *[n];
huffmanCoding(huffTree,huffCode,n);
cout<<endl;
for(int i=0;i<n;i++){
cout << huffCode[i]<< endl;
}
delete w;
delete huffTree;
for(int i=0;i<n;i++){ //删除二维数组,先循环删除每个*huffCode
cout<<"delete 第"<<i<<"个元素"<<endl;
delete[] huffCode[i];
//TODO
}
cout<<"delete";
delete [] huffCode;//再删除**huffCode
return 0;
}
补充1:
对于内置类型而言,new仅仅是分配内存,除非后面显示加(),相当于调用它的构造函数,对于自定义类型而言,只要一调用new,那么编译器不仅仅给它分配内存,还调用它的默认构造函数初始化,即使后面没有加()。
new(多个对象)数组
new分配的对象,不管单个对象还是多个对象的分配,都是默认初始化。 但可以对数组进行值初始化,方法就是:在大小之后添加一对空括号。
int *pia = new int [ 10 ]; // 10个未初始化int
int *pia2 = new int [ 10 ](); // 10个值初始化为0的int
补充2:
使用new [ ]申请的内存释放时要用delete [ ]