哈夫曼树

来源:互联网 发布:数据分析师 泉州 编辑:程序博客网 时间:2024/06/11 05:25

//哈夫曼编码:对给定串进行不等长加密,每个字母都用0、1表示

//思路:每次选频次最少的结点形成一个树的左右子树,结点值为两子数之和,递归进行,直到建立一棵树

#include<iostream> #include<cstring>using namespace std;int is_Exist[1000];struct Node{char ch;int times;Node* LeftNode;Node* RightNode;}*list[1000];int CreatNode()//以字母出现频次建立一颗树{char word[1000];int i = 0; is_Exist[0] = 1;scanf("%s", &word);list[0] = new Node;list[0]->ch = word[0];list[0]->times = 1;list[0]->LeftNode = NULL;list[0]->RightNode = NULL;i++;for (int j =1; j < strlen(word); j++){int is_occur = 0;int k;for( k = 0; k < i; k++){if (list[k]->ch == word[j]){is_occur = 1;list[k]->times++;break;}}if (is_occur == 0) {list[i] = new Node;list[i]->ch = word[j];list[i]->times = 1;list[i]->LeftNode = NULL;list[i]->RightNode = NULL;is_Exist[i] = 1;i++;}}return i;}int Start_Code(int i,int num)//i是数组总长度 num是没进树的叶子个数  递归进行加密{int is_num =0;for (int j = 0; j < i; j++){if (is_Exist[j] == 1){is_num++;}}if (is_num== 1) return i;else{int min1 = 0, min2 = 0;for (int j = 0; j < i; j++) {if (is_Exist[j] == 1){min1 = j; break;}}for (int j = 0; j < i; j++) {if (is_Exist[j] == 1 && list[j]->times < list[min1]->times) min1 = j; }for (int j = 0; j < i; j++){if (is_Exist[j] == 1&&j!=min1){min2 = j;break;}}for (int j = 0; j < i; j++) {if (is_Exist[j] == 1 && list[j]->times <= list[min2]->times&&j != min1)  min2 = j; }list[i] = new Node; is_Exist[i] = 1;list[i]->times = list[min1]->times + list[min2]->times;list[i]->LeftNode = list[min1];list[i]->RightNode = list[min2];is_Exist[min1] = 0; is_Exist[min2] = 0;i++;Start_Code(i, num);}}void leaf_out(Node* &T)//对于加密之后的叶子路径挨个进行输出{printf("编码方式如下:\n");Node* buffer[1000];//层次遍历存结点string re[1000];//和buffer一一对应 用来保存每个结点的路径buffer[0] = T;re[0] = "";int p = 0, q = 1;//p是当前扫到的元素下标  q是应扫到的元素下标if (T != NULL){buffer[0] = T;//新建一个buffer数组 让第一个元素为树的根结点for (p = 0; p<q; p++){int w = 0;if (buffer[p]->LeftNode != NULL)//如果左节点不为空 即把这个节点放到队尾(下层遍历时遍历到){buffer[q] = buffer[p]->LeftNode;re[q].assign(re[p]);re[q]=re[q].append("1");q++;w = 1;}if (buffer[p]->RightNode != NULL)//如果右节点不为空 即把这个节点放到队尾(下层遍历时遍历到){buffer[q] = buffer[p]->RightNode;re[q].assign(re[p]);re[q] = re[q].append("0");q++;w= 1;}if (w == 0){printf("%c:", buffer[p]->ch);for (int i = 0; i <re[p].size(); i++) printf("%c", re[p][i]);printf("\n");}}}else{printf("NULL");}}int main(){int num_leaf=CreatNode();int num_lastnode = Start_Code(num_leaf, num_leaf)-1;leaf_out(list[num_lastnode]);return 0;}


//第一次码博客 光贴代码得了

0 0
原创粉丝点击