数据结构-树-哈夫曼树
概念
路径和路径长度
在一棵树中,从一个节点往下可以达到的孩子或孙子节点之间的通过,称为路径。通路中分支的数目称为路径长度。若规定根节点的层数为1,则从根节点到第L层节点的路径长度为L-1
节点的权及带权路径长度
若将树中节点赋给一个有着某种意义的数值,则这个数值称为该结点的权,节点的带权路径长度为:从根节点到该结点之间的路径长度与该结点的权的乘积
树的带权路径长度
树的带权路径长度规定为所有叶子节点的带权路径长度和,记为WPL(weighted path length),权值越大的节点离根节点越近的二叉树才是最优二叉树
WPL最小的树就是哈夫曼树
生成哈夫曼树流程
1 从小到大排序,将每个数据看成一个节点,每个节点可以看为一个最简单二叉树来处理
2 找出根节点权值最小的两个数
3 组成一颗新的二叉树,该新的二叉树的权值是组成的二叉树的权值的和
4 继续循环,知道所有数据处理完毕
Huffman编码
代码实现-huffman树
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 #include<stdio.h> 4 using namespace std; 5 #define MAXNODENUM 100 //假设最多节点为100个 6 #define MAXCODENUM 100 //假设编码最多100位 7 typedef struct BinaryNode 8 { 9 int value; 10 int flag; 11 struct BinaryNode* parent; 12 struct BinaryNode* lchild; 13 struct BinaryNode* rchild; 14 }HF_NODE,*PHF_NODE; 15 typedef struct 16 { 17 int HuffmanCode[MAXCODENUM]; 18 int start; 19 }huffcode,*phuffcode; 20 void PreOrderTraverse(PHF_NODE a) 21 { 22 if (a == NULL) 23 return; 24 printf("%d\n", a->value); 25 PreOrderTraverse(a->lchild); 26 PreOrderTraverse(a->rchild); 27 } 28 void InitHuffmanTree(PHF_NODE head, int SumNumNode) 29 { 30 PHF_NODE Min_Location1=NULL, Min_Location2=NULL;//定义最小的两个节点的指针 31 int Min1=0, Min2=0;//定义最小的两个数的标志 32 //一共还要初始化n-1个节点 33 for (int i = SumNumNode; i < 2*SumNumNode - 1; i++) 34 { 35 //找出最小的第一颗树 36 for (int j = 0; j < 2 * SumNumNode-1; j++) 37 { 38 if (head[j].value == 0) 39 { 40 continue;//如果权值为0直接略过 41 } 42 if (head[j].flag == 1) 43 { 44 continue;//如果flag位为1也直接略过 45 } 46 //用不是空,且flag=0的节点来假设为最小节点 47 Min_Location1 = head + j; 48 Min1 = Min_Location1->value; 49 for (int t = 0; t < 2 * SumNumNode - 1; t++)//找出最小的第一颗树 50 { 51 if (head[t].value == 0) 52 { 53 continue;//如果权值为0直接略过 54 } 55 if (head[t].flag == 1) 56 { 57 continue;//如果flag位为1也直接略过 58 } 59 if (head[t].value < Min1) 60 { 61 Min_Location1 = head + t; 62 Min1 = head[t].value; 63 } 64 } 65 Min_Location1->flag = 1; 66 break; 67 } 68 //找出最小的第二颗树 69 for (int j = 0; j < 2 * SumNumNode - 1; j++)//找出最小的第一颗树 70 { 71 if (head[j].value == 0) 72 { 73 continue;//如果权值为0直接略过 74 } 75 if (head[j].flag == 1) 76 { 77 continue;//如果flag位为1也直接略过 78 } 79 //用不是空,且flag=0的节点来假设为最小节点 80 Min_Location2 = head + j; 81 Min2 = Min_Location2->value; 82 for (int t = 0; t < 2 * SumNumNode - 1; t++)//找出最小的第二颗树 83 { 84 if (head[t].value == 0) 85 { 86 continue;//如果权值为0直接略过 87 } 88 if (head[t].flag == 1) 89 { 90 continue;//如果flag位为1也直接略过 91 } 92 if (head[t].value < Min1) 93 { 94 Min_Location2 = head + t; 95 Min2 = head[t].value; 96 } 97 } 98 Min_Location2->flag = 1; 99 break; 100 } 101 102 if (Min_Location1 == NULL || Min_Location2 == NULL) 103 { 104 return; 105 } 106 //建立新节点联系上 107 head[i].lchild = Min_Location1; 108 head[i].rchild = Min_Location2; 109 head[i].value = Min1 + Min2; 110 111 Min_Location1->parent = head + i; 112 Min_Location2->parent = head + i; 113 114 Min_Location1 = NULL; 115 Min_Location2 = NULL; 116 Min1 = 0; 117 Min2 = 0; 118 } 119 } 120 PHF_NODE GetRootNode(PHF_NODE head, int SumNumNode) 121 { 122 for (int i = 0; i < 2 * SumNumNode - 1; i++) 123 { 124 if (head[i].parent == NULL) 125 { 126 return head + i; 127 } 128 } 129 return NULL; 130 } 131 132 void HuffmanTree() 133 { 134 HF_NODE hf_node[MAXNODENUM];//定义最大节点数 135 136 printf("please input node's num,最多为50个\n"); 137 int SumNumNode; 138 scanf("%d", &SumNumNode); 139 for (int i = 0; i < SumNumNode * 2 - 1; i++)//初始化所有节点数 140 { 141 hf_node[i].value = 0; 142 hf_node[i].flag = 0; 143 hf_node[i].parent = NULL; 144 hf_node[i].lchild = NULL; 145 hf_node[i].rchild = NULL; 146 } 147 printf("please input leaf node value\n"); 148 //输入初始化节点的value 149 for (int i = 0; i < SumNumNode; i++) 150 { 151 scanf("%d",&(hf_node[i].value)); 152 } 153 //创建huffman树 154 InitHuffmanTree(hf_node, SumNumNode); 155 PHF_NODE root = GetRootNode(hf_node,SumNumNode); 156 PreOrderTraverse(root); 157 HuffmanCode(hf_node, SumNumNode * 2 - 1); 158 } 159 160 161 162 163 int main() 164 { 165 HuffmanTree(); 166 return 0; 167 }