class Node {
char: string | null;
freq: number;
left: Node | null;
right: Node | null;
constructor(char: string | null, freq: number, left: Node | null = null, right: Node | null = null) {
this.char = char;
this.freq = freq;
this.left = left;
this.right = right;
}
}
function buildHuffmanTree(chars: string[], freqs: number[]): Node | null {
let nodes: Node[] = [];
for (let i = 0; i < chars.length; i++) {
nodes.push(new Node(chars[i], freqs[i]));
}
if (nodes.length === 0) return null;
while (nodes.length > 1) {
nodes.sort((a, b) => a.freq - b.freq); // sort by freq ascending
const left = nodes.shift()!; // smallest freq
const right = nodes.shift()!; // next smallest freq
const merged = new Node(null, left.freq + right.freq, left, right);
nodes.push(merged);
}
return nodes[0];
}
function generateCodes(node: Node | null, prefix: string, codes: Map<string, string>) {
if (!node) return;
if (node.char !== null) {
codes.set(node.char, prefix);
} else {
generateCodes(node.left, prefix + '0', codes);
generateCodes(node.right, prefix + '1', codes);
}
}
// Driver code
const chars = ['a', 'b', 'c', 'd', 'e', 'f'];
const freqs = [5, 9, 12, 13, 16, 45];
const root = buildHuffmanTree(chars, freqs);
const codes = new Map<string, string>();
generateCodes(root, '', codes);
for (const c of chars) {
console.log(`${c}:${codes.get(c)}`);
}nodes.sort((a, b) => a.freq - b.freq);
sort nodes by frequency ascending to pick smallest two
const left = nodes.shift()!; const right = nodes.shift()!;
remove two smallest nodes to merge
const merged = new Node(null, left.freq + right.freq, left, right);
create new internal node with combined frequency
add merged node back to list for next iteration
if (node.char !== null) { codes.set(node.char, prefix); }
assign code to leaf node character
generateCodes(node.left, prefix + '0', codes); generateCodes(node.right, prefix + '1', codes);
traverse left and right children adding '0' or '1' to code
a:1100
b:1101
c:100
d:101
e:111
f:0