Skip to content

Commit 3767288

Browse files
committed
fix: align Huffman tree ordering across languages
1 parent 068c8ac commit 3767288

4 files changed

Lines changed: 23 additions & 6 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Huffman 跨语言互通修正
2+
3+
日期:2026-03-13
4+
5+
## 变更内容
6+
7+
- 统一 C++、Go、Rust 三个 Huffman 实现的树构建平局决策
8+
- 在合并节点时保留子树最小符号作为排序键,避免不同语言生成不兼容码表
9+
- 修复 correctness workflow 中 `C++ encode -> Go/Rust decode` 的跨语言失败
10+
11+
## 背景
12+
13+
三个实现都使用“频率优先、符号次序兜底”的最小堆来构建 Huffman 树,但内部节点此前统一写死 `symbol = 0`,会让不同语言在频率相同的场景下以不同顺序继续合并,最终得到各自 round-trip 正常、跨语言互解失败的码表。此次将内部节点排序键收敛到一致规则后,跨语言输出恢复兼容。

huffman/cpp/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static Node* build_tree(const std::vector<uint32_t>& freq) {
111111
Node* only = pq.top();
112112
pq.pop();
113113
Node* parent = new Node;
114-
parent->symbol = 0;
114+
parent->symbol = only->symbol;
115115
parent->freq = only->freq;
116116
parent->left = only;
117117
parent->right = nullptr;
@@ -123,7 +123,7 @@ static Node* build_tree(const std::vector<uint32_t>& freq) {
123123
Node* b = pq.top();
124124
pq.pop();
125125
Node* parent = new Node;
126-
parent->symbol = 0;
126+
parent->symbol = a->symbol < b->symbol ? a->symbol : b->symbol;
127127
parent->freq = a->freq + b->freq;
128128
parent->left = a;
129129
parent->right = b;

huffman/go/main.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,18 @@ func buildTree(freq []uint32) *Node {
7070
}
7171
if h.Len() == 1 {
7272
only := heap.Pop(h).(*Node)
73-
parent := &Node{symbol: 0, freq: only.freq, left: only, right: nil}
73+
parent := &Node{symbol: only.symbol, freq: only.freq, left: only, right: nil}
7474
heap.Push(h, parent)
7575
}
7676
for h.Len() > 1 {
7777
a := heap.Pop(h).(*Node)
7878
b := heap.Pop(h).(*Node)
79+
minSymbol := a.symbol
80+
if b.symbol < minSymbol {
81+
minSymbol = b.symbol
82+
}
7983
parent := &Node{
80-
symbol: 0,
84+
symbol: minSymbol,
8185
freq: a.freq + b.freq,
8286
left: a,
8387
right: b,

huffman/rust/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ fn build_tree(freq: &[u32]) -> Box<Node> {
7878
let item = heap.pop().unwrap();
7979
let only = item.node;
8080
let parent = Box::new(Node {
81-
symbol: 0,
81+
symbol: only.symbol,
8282
freq: only.freq,
8383
left: Some(only),
8484
right: None,
@@ -94,7 +94,7 @@ fn build_tree(freq: &[u32]) -> Box<Node> {
9494
let b = heap.pop().unwrap().node;
9595
let freq_sum = a.freq + b.freq;
9696
let parent = Box::new(Node {
97-
symbol: 0,
97+
symbol: a.symbol.min(b.symbol),
9898
freq: freq_sum,
9999
left: Some(a),
100100
right: Some(b),

0 commit comments

Comments
 (0)