Сжатие методом Шенона-Фано
Créé le : 13 octobre 2025
Répondu en utilisant GPT-5 Thinking par Chat01
Créé le : 13 octobre 2025
Répondu en utilisant GPT-5 Thinking par Chat01
Сжатие методом Шенона-Фано
Вот краткое, наглядное объяснение метода Шеннона–Фано для сжатия.
Шеннон–Фано — способ построения префиксного (мгновенно декодируемого) кода для алфавита с известными частотами. Идея: чаще встречающимся символам давать более короткие коды.
0, правой — 1.Строка: BANANA
Частоты: A×3, N×2, B×1 → вероятности: A=0.5, N≈0.333, B≈0.167.
Деление:
01
10, B (0.167) → 11Коды: A=0, N=10, B=11.
Кодируем BANANA → 11 0 10 0 10 0 = 9 бит.
Фиксированный код для 3 символов дал бы 2 бита/символ × 6 = 12 бит → экономия ~25%.
pythonfrom collections import Counter def shannon_fano(symbols): # symbols: dict {symbol: freq} items = sorted(symbols.items(), key=lambda x: x[1], reverse=True) codes = {} def split_code(seq, prefix=""): if len(seq) == 1: sym, _ = seq[0] codes[sym] = prefix or "0" # на случай 1 символа return total = sum(w for _, w in seq) acc = 0 # точка разреза с суммами как можно ближе cut = 0 best_diff = float("inf") for i in range(1, len(seq)): acc += seq[i-1][1] diff = abs(total/2 - acc) if diff < best_diff: best_diff = diff cut = i left, right = seq[:cut], seq[cut:] split_code(left, prefix + "0") split_code(right, prefix + "1") split_code(items) return codes # пример s = "BANANA" freqs = Counter(s) codes = shannon_fano(freqs) encoded = "".join(codes[ch] for ch in s) codes, encoded, len(encoded)
Если хотите, могу: