Data update
This commit is contained in:
parent
07c7092a52
commit
61b93a2cd1
313 changed files with 6160 additions and 346 deletions
135
Task/Huffman-coding/Zig/huffman-coding.zig
Normal file
135
Task/Huffman-coding/Zig/huffman-coding.zig
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
const std = @import("std");
|
||||
|
||||
const Node = struct {
|
||||
frequency: usize,
|
||||
kind: union(enum) {
|
||||
internal: struct {
|
||||
left: *Node,
|
||||
right: *Node,
|
||||
},
|
||||
leaf: u8,
|
||||
},
|
||||
|
||||
fn initLeaf(frequency: usize, ch: u8) Node {
|
||||
return .{
|
||||
.frequency = frequency,
|
||||
.kind = .{ .leaf = ch },
|
||||
};
|
||||
}
|
||||
|
||||
fn initInternal(
|
||||
allocator: std.mem.Allocator,
|
||||
left_child: Node,
|
||||
right_child: Node,
|
||||
) !Node {
|
||||
const left = try allocator.create(Node);
|
||||
const right = try allocator.create(Node);
|
||||
left.* = left_child;
|
||||
right.* = right_child;
|
||||
return .{
|
||||
.frequency = left_child.frequency + right_child.frequency,
|
||||
.kind = .{ .internal = .{ .left = left, .right = right } },
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: Node, allocator: std.mem.Allocator) void {
|
||||
switch (self.kind) {
|
||||
.internal => |inner| {
|
||||
inner.left.deinit(allocator);
|
||||
inner.right.deinit(allocator);
|
||||
allocator.destroy(inner.left);
|
||||
allocator.destroy(inner.right);
|
||||
},
|
||||
.leaf => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn compare(context: void, a: Node, b: Node) std.math.Order {
|
||||
_ = context;
|
||||
return std.math.order(a.frequency, b.frequency);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
const text = "this is an example for huffman encoding";
|
||||
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer std.debug.assert(gpa.deinit() == .ok);
|
||||
|
||||
const allocator = gpa.allocator();
|
||||
var frequencies = std.AutoHashMap(u8, usize).init(allocator);
|
||||
defer frequencies.deinit();
|
||||
|
||||
for (text) |ch| {
|
||||
const gop = try frequencies.getOrPut(ch);
|
||||
if (gop.found_existing) {
|
||||
gop.value_ptr.* += 1;
|
||||
} else {
|
||||
gop.value_ptr.* = 1;
|
||||
}
|
||||
}
|
||||
|
||||
var prioritized_frequencies =
|
||||
std.PriorityQueue(Node, void, Node.compare).init(allocator, {});
|
||||
defer prioritized_frequencies.deinit();
|
||||
|
||||
var freq_it = frequencies.iterator();
|
||||
while (freq_it.next()) |counted_char| {
|
||||
try prioritized_frequencies.add(Node.initLeaf(
|
||||
counted_char.value_ptr.*,
|
||||
counted_char.key_ptr.*,
|
||||
));
|
||||
}
|
||||
|
||||
while (prioritized_frequencies.len > 1) {
|
||||
try prioritized_frequencies.add(try Node.initInternal(
|
||||
allocator,
|
||||
prioritized_frequencies.remove(),
|
||||
prioritized_frequencies.remove(),
|
||||
));
|
||||
}
|
||||
|
||||
const root = prioritized_frequencies.items[0];
|
||||
defer root.deinit(allocator);
|
||||
|
||||
var codes = std.AutoArrayHashMap(u8, []const u8).init(allocator);
|
||||
defer codes.deinit();
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
try generateCodes(arena.allocator(), &root, &.{}, &codes);
|
||||
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
var code_it = codes.iterator();
|
||||
while (code_it.next()) |item| {
|
||||
try stdout.print("{c}: {s}\n", .{
|
||||
item.key_ptr.*,
|
||||
item.value_ptr.*,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn generateCodes(
|
||||
arena: std.mem.Allocator,
|
||||
node: *const Node,
|
||||
prefix: []const u8,
|
||||
out_codes: *std.AutoArrayHashMap(u8, []const u8),
|
||||
) !void {
|
||||
switch (node.kind) {
|
||||
.internal => |inner| {
|
||||
const left_prefix = try arena.alloc(u8, prefix.len + 1);
|
||||
std.mem.copy(u8, left_prefix, prefix);
|
||||
left_prefix[prefix.len] = '0';
|
||||
try generateCodes(arena, inner.left, left_prefix, out_codes);
|
||||
|
||||
const right_prefix = try arena.alloc(u8, prefix.len + 1);
|
||||
std.mem.copy(u8, right_prefix, prefix);
|
||||
right_prefix[prefix.len] = '1';
|
||||
try generateCodes(arena, inner.right, right_prefix, out_codes);
|
||||
},
|
||||
.leaf => |ch| {
|
||||
try out_codes.put(ch, prefix);
|
||||
},
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue