11:36:53 2019-08-30
学习
09:42:25 2019-08-31
补完昨天未写完的并查集优化
带权路径长度(WPL) (Weighted Path Length of Tree),设二叉树有n个叶子节点,每个叶子节点带有权值${w_k}$,从根节点到每个叶子节点的长度为${l_k}$,则每个叶子节点的带权路径长度之和就是:${WPL}=\displaystyle \sum_{k=1}^n{w_k}{l_k}$
最优二叉树或哈夫曼树:WPL最小的二叉树
哈夫曼树的构造:每次把权值最小的两课二叉树合并
利用最小堆 实现哈夫曼树:
1 #include<stdio.h> 2 #include<malloc.h> 3 4 typedef struct TreeNode* HuffmanTree; 5 struct TreeNode 6 { 7 int Weight; //权重 8 HuffmanTree Right, Left; 9 }; 10 typedef struct HeapStruct* MinHeap; 11 struct HeapStruct 12 { 13 HuffmanTree* Elements; 14 int Capacity; 15 int Size; 16 }; 17 18 MinHeap Create(int MaxSize); //创造一个空的最小堆 19 int IsFull(MinHeap H); 20 void Insert(MinHeap H, HuffmanTree T); 21 HuffmanTree DeleteMin(MinHeap H); //删除一个权重最小的节点 并返回 22 23 MinHeap Create(int MaxSize) 24 { 25 MinHeap H = (MinHeap)malloc(sizeof(struct HeapStruct)); 26 H->Elements = (HuffmanTree*)malloc(sizeof(struct TreeNode) * (MaxSize + 1)); 27 H->Capacity = MaxSize; 28 H->Size = 0; 29 H->Elements[0]->Weight = -1; //设置哨兵 30 return H; 31 } 32 int IsFull(MinHeap H) 33 { 34 return (H->Size == H->Capacity) ? 1 : 0; 35 } 36 void Insert(MinHeap H, HuffmanTree T) 37 { 38 if (IsFull(H)) 39 return; 40 int i = ++H->Size; 41 for (; T->Weight < H->Elements[i / 2]->Weight; i /= 2) 42 H->Elements[i] = H->Elements[i / 2]; 43 H->Elements[i] = T; 44 } 45 HuffmanTree DeleteMin(MinHeap H) 46 { 47 if (IsFull(H)) 48 return; 49 HuffmanTree MinItem = H->Elements[1]; 50 HuffmanTree Tmp = H->Elements[H->Size--]; 51 int Parent, Child; //这俩个记录的是位置 52 for (Parent = 1; Parent * 2 <= H->Size; Parent = Child) 53 { 54 Child = Parent * 2; 55 if (Child != H->Size && H->Elements[Child]->Weight > H->Elements[Child + 1]->Weight) 56 Child++; 57 if (Tmp->Weight <= H->Elements[Child]->Weight)break; //注意这边 找到后就立即结束循环 这样才能添加到正确位置 58 else 59 H->Elements[Parent] = H->Elements[Child]; 60 } 61 H->Elements[Parent] = Tmp; 62 return MinItem; 63 } 64 65 //建立最小堆 66 //元素已经读入 67 void PercDown(MinHeap H, int i) 68 { 69 int Parent, Child; 70 HuffmanTree Tmp = H->Elements[i]; 71 for (Parent = i; Parent * 2 <= H->Size; Parent = Child) 72 { 73 Child = Parent * 2; 74 if ((Child != H->Size) && (H->Elements[Child]->Weight > H->Elements[Child + 1]->Weight)) 75 Child++; 76 if (Tmp->Weight <= H->Elements[Child]->Weight)break; 77 else 78 H->Elements[Parent] = H->Elements[Child]; 79 } 80 H->Elements[Parent] = Tmp; 81 } 82 void BuildMinHeap(MinHeap H) 83 { 84 for (int i = H->Size / 2; i > 0; i--) //从最后一个有子节点的父节点开始 85 PercDown(H, i); 86 } 87 88 //利用最小堆 构建哈夫曼树 89 //每次把权值最小的两颗二叉树合并 90 HuffmanTree Huffman(MinHeap H) 91 { //假设H->Size个权值已经存在H->Elements[]->Weight里 92 int i; 93 HuffmanTree T; 94 BuildMinHeap(H); //将H->Elements[]按照权重调整为最小堆 95 for (int i = 1; i < H->Size; i++) //H->Size个元素合并 总共需要H->Size-1次 96 { 97 T = (HuffmanTree)malloc(sizeof(struct TreeNode)); 98 T->Left = DeleteMin(H); //取出权重最小的元素 作为T的左节点 99 T->Right = DeleteMin(H); //取出权重最小的元素 作为T的右节点 100 T->Weight = T->Left->Weight + T->Right->Weight; //计算新的权重 101 Insert(H, T); //将新T插入最小堆中; 102 } 103 T = DeleteMin(H); 104 return T; 105 }