Skip to content

Commit ae9f05c

Browse files
Implemented a stack (#21)
1 parent 4e17826 commit ae9f05c

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed

build.zig

+7
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ pub fn build(b: *std.Build) void {
8181
.name = "lruCache.zig",
8282
.category = "dataStructures",
8383
});
84+
if (std.mem.eql(u8, op, "ds/stack"))
85+
build_algorithm(b, .{
86+
.optimize = optimize,
87+
.target = target,
88+
.name = "stack.zig",
89+
.category = "dataStructures",
90+
});
8491

8592
// Dynamic Programming algorithms
8693
if (std.mem.eql(u8, op, "dp/coinChange"))

dataStructures/stack.zig

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
const std = @import("std");
2+
const testing = std.testing;
3+
4+
const errors = error{EmptyList};
5+
6+
// Returns a stack instance.
7+
// Arguments:
8+
// T: the type of the info(i.e. i32, i16, u8, etc...)
9+
// Allocator: This is needed for the struct instance. In most cases,
10+
// feel free to use std.heap.GeneralPurposeAllocator
11+
pub fn stack(comptime T: type) type {
12+
return struct {
13+
const Self = @This();
14+
15+
// This is the node struct. It holds:
16+
// info: T
17+
// next: A pointer to the next element
18+
// prev: A pointer to the previous element
19+
pub const node = struct {
20+
info: T,
21+
next: ?*node = null,
22+
prev: ?*node = null,
23+
};
24+
25+
allocator: *std.mem.Allocator,
26+
root: ?*node = null,
27+
size: usize = 0,
28+
29+
// Function that inserts elements to the stack
30+
// Runs in O(1)
31+
// Arguments:
32+
// key: T - the key to be inserted to the stack
33+
pub fn push(self: *Self, key: T) !void {
34+
const nn = try self.allocator.create(node);
35+
nn.* = node{ .info = key };
36+
37+
if (self.root == null) {
38+
self.root = nn;
39+
self.size += 1;
40+
return;
41+
} else {
42+
self.root.?.next = nn;
43+
nn.prev = self.root;
44+
self.root = nn;
45+
self.size += 1;
46+
}
47+
}
48+
49+
// Function that returns the top of the stack
50+
// Runs in O(1)
51+
// Returns an EmptyList error if the list is empty
52+
pub fn top(self: *Self) errors!T {
53+
return if (self.root != null) self.root.?.info else errors.EmptyList;
54+
}
55+
56+
// Function that removes the top of the stack
57+
// Runs in O(1)
58+
// Returns an EmptyList error if the list is empty
59+
pub fn pop(self: *Self) errors!void {
60+
if (self.root == null) {
61+
return errors.EmptyList;
62+
}
63+
64+
const curr: *node = self.root.?;
65+
defer self.allocator.destroy(curr);
66+
67+
self.root = self.root.?.prev;
68+
self.size -= 1;
69+
}
70+
71+
// Function that destroys the allocated memory of the whole stack
72+
pub fn destroy(self: *Self) !void {
73+
while (self.size != 0) : (try self.pop()) {}
74+
self.size = 0;
75+
}
76+
};
77+
}
78+
79+
test "Testing insertion/popping in stack" {
80+
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
81+
defer _ = gpa.deinit();
82+
var allocator = gpa.allocator();
83+
84+
var s = stack(i32){ .allocator = &allocator };
85+
86+
try s.push(10);
87+
try s.push(20);
88+
try s.push(30);
89+
try testing.expect(try s.top() == 30);
90+
try testing.expect(s.size == 3);
91+
try s.pop();
92+
try testing.expect(try s.top() == 20);
93+
try testing.expect(s.size == 2);
94+
try s.pop();
95+
try testing.expect(try s.top() == 10);
96+
try testing.expect(s.size == 1);
97+
try s.pop();
98+
s.pop() catch |err| {
99+
try testing.expect(err == error.EmptyList);
100+
return;
101+
};
102+
try testing.expect(s.size == 0);
103+
try s.destroy();
104+
}
105+
106+
test "Testing other formats" {
107+
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
108+
defer _ = gpa.deinit();
109+
var allocator = gpa.allocator();
110+
111+
var s = stack(u8){ .allocator = &allocator };
112+
113+
try s.push('a');
114+
try s.push('b');
115+
try s.push('c');
116+
117+
try testing.expect(try s.top() == 'c');
118+
try s.pop();
119+
try testing.expect(try s.top() == 'b');
120+
try s.push('w');
121+
try testing.expect(try s.top() == 'w');
122+
123+
try s.destroy();
124+
}

runall.cmd

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ rem Data Structures
2121
%ZIG_TEST% -Dalgorithm=ds/linkedlist %Args%
2222
%ZIG_TEST% -Dalgorithm=ds/doublylinkedlist %Args%
2323
%ZIG_TEST% -Dalgorithm=ds/lrucache %Args%
24+
%ZIG_TEST% -Dalgorithm=ds/stack %Args%
2425

2526
rem Dynamic Programming
2627
%ZIG_TEST% -Dalgorithm=dp/coinChange %Args%

runall.sh

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ $ZIG_TEST -Dalgorithm=math/gcd $Args
2121
$ZIG_TEST -Dalgorithm=ds/linkedlist $Args
2222
$ZIG_TEST -Dalgorithm=ds/doublylinkedlist $Args
2323
$ZIG_TEST -Dalgorithm=ds/lrucache $Args
24+
$ZIG_TEST -Dalgorithm=ds/stack $Args
2425

2526
# Dynamic Programming
2627
$ZIG_TEST -Dalgorithm=dp/coinChange $Args

0 commit comments

Comments
 (0)