-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmy_heap.zig
186 lines (158 loc) · 6.24 KB
/
my_heap.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// File: my_heap.zig
// Created Time: 2023-01-14
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// 堆类简易实现
pub fn MaxHeap(comptime T: type) type {
return struct {
const Self = @This();
max_heap: ?std.ArrayList(T) = null, // 使用列表而非数组,这样无需考虑扩容问题
// 构造函数,根据输入列表建堆
pub fn init(self: *Self, allocator: std.mem.Allocator, nums: []const T) !void {
if (self.max_heap != null) return;
self.max_heap = std.ArrayList(T).init(allocator);
// 将列表元素原封不动添加进堆
try self.max_heap.?.appendSlice(nums);
// 堆化除叶节点以外的其他所有节点
var i: usize = parent(self.size() - 1) + 1;
while (i > 0) : (i -= 1) {
try self.siftDown(i - 1);
}
}
// 析构函数,释放内存
pub fn deinit(self: *Self) void {
if (self.max_heap != null) self.max_heap.?.deinit();
}
// 获取左子节点索引
fn left(i: usize) usize {
return 2 * i + 1;
}
// 获取右子节点索引
fn right(i: usize) usize {
return 2 * i + 2;
}
// 获取父节点索引
fn parent(i: usize) usize {
// return (i - 1) / 2; // 向下整除
return @divFloor(i - 1, 2);
}
// 交换元素
fn swap(self: *Self, i: usize, j: usize) !void {
var tmp = self.max_heap.?.items[i];
try self.max_heap.?.replaceRange(i, 1, &[_]T{self.max_heap.?.items[j]});
try self.max_heap.?.replaceRange(j, 1, &[_]T{tmp});
}
// 获取堆大小
pub fn size(self: *Self) usize {
return self.max_heap.?.items.len;
}
// 判断堆是否为空
pub fn isEmpty(self: *Self) bool {
return self.size() == 0;
}
// 访问堆顶元素
pub fn peek(self: *Self) T {
return self.max_heap.?.items[0];
}
// 元素入堆
pub fn push(self: *Self, val: T) !void {
// 添加节点
try self.max_heap.?.append(val);
// 从底至顶堆化
try self.siftUp(self.size() - 1);
}
// 从节点 i 开始,从底至顶堆化
fn siftUp(self: *Self, i_: usize) !void {
var i = i_;
while (true) {
// 获取节点 i 的父节点
var p = parent(i);
// 当“越过根节点”或“节点无需修复”时,结束堆化
if (p < 0 or self.max_heap.?.items[i] <= self.max_heap.?.items[p]) break;
// 交换两节点
try self.swap(i, p);
// 循环向上堆化
i = p;
}
}
// 元素出堆
pub fn pop(self: *Self) !T {
// 判断处理
if (self.isEmpty()) unreachable;
// 交换根节点与最右叶节点(即交换首元素与尾元素)
try self.swap(0, self.size() - 1);
// 删除节点
var val = self.max_heap.?.pop();
// 从顶至底堆化
try self.siftDown(0);
// 返回堆顶元素
return val;
}
// 从节点 i 开���,从顶至底堆化
fn siftDown(self: *Self, i_: usize) !void {
var i = i_;
while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 ma
var l = left(i);
var r = right(i);
var ma = i;
if (l < self.size() and self.max_heap.?.items[l] > self.max_heap.?.items[ma]) ma = l;
if (r < self.size() and self.max_heap.?.items[r] > self.max_heap.?.items[ma]) ma = r;
// 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if (ma == i) break;
// 交换两节点
try self.swap(i, ma);
// 循环向下堆化
i = ma;
}
}
fn lessThan(context: void, a: T, b: T) std.math.Order {
_ = context;
return std.math.order(a, b);
}
fn greaterThan(context: void, a: T, b: T) std.math.Order {
return lessThan(context, a, b).invert();
}
// 打印堆(二叉树)
pub fn print(self: *Self, mem_allocator: std.mem.Allocator) !void {
const PQgt = std.PriorityQueue(T, void, greaterThan);
var queue = PQgt.init(std.heap.page_allocator, {});
defer queue.deinit();
try queue.addSlice(self.max_heap.?.items);
try inc.PrintUtil.printHeap(T, mem_allocator, queue);
}
};
}
// Driver Code
pub fn main() !void {
// 初始化内存分配器
var mem_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer mem_arena.deinit();
const mem_allocator = mem_arena.allocator();
// 初始化大顶堆
var max_heap = MaxHeap(i32){};
try max_heap.init(std.heap.page_allocator, &[_]i32{ 9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2 });
defer max_heap.deinit();
std.debug.print("\n输入列表并建堆后\n", .{});
try max_heap.print(mem_allocator);
// 获取堆顶元素
var peek = max_heap.peek();
std.debug.print("\n堆顶元素为 {}\n", .{peek});
// 元素入堆
const val = 7;
try max_heap.push(val);
std.debug.print("\n元素 {} 入堆后\n", .{val});
try max_heap.print(mem_allocator);
// 堆顶元素出堆
peek = try max_heap.pop();
std.debug.print("\n堆顶元素 {} 出堆后\n", .{peek});
try max_heap.print(mem_allocator);
// 获取堆的大小
var size = max_heap.size();
std.debug.print("\n堆元素数量为 {}", .{size});
// 判断堆是否为空
var is_empty = max_heap.isEmpty();
std.debug.print("\n堆是否为空 {}\n", .{is_empty});
_ = try std.io.getStdIn().reader().readByte();
}