{"id":83,"date":"2026-02-11T05:51:00","date_gmt":"2026-02-11T05:51:00","guid":{"rendered":"https:\/\/mattbick.dev\/?p=83"},"modified":"2026-02-10T17:52:47","modified_gmt":"2026-02-10T17:52:47","slug":"data-structure-every-day-day-4-stack","status":"publish","type":"post","link":"https:\/\/mattbick.dev\/?p=83","title":{"rendered":"Data Structure Every Day, Day 4: Stack"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Over the last three posts, we created a tailless linked list, extended it into a tailed list, and finally we implemented a double linked list that solved the O(n) complexity hurdles. Each step added speed, but with that came some tradeoffs along with complexity. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For Day 4, I have decided that the next logical step is to implement a Stack data structure, but instead of starting from raw memory and building everything from scratch, we\u2019re going to focus on behavior and benchmarks first (this will all make sense at the end of the blog post so hang with me).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">What Is a Stack?<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">A stack is one of the simplest and most fundamental data structures in computer science.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It follows a single rule:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Last In, First Out (LIFO)<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you push items onto a stack:<\/p>\n\n\n\n<pre data-line=\"\" class=\"wp-block-prismatic-blocks\"><code class=\"language-\">Push A\nPush B\nPush C<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then popping removes them in reverse order:<\/p>\n\n\n\n<pre data-line=\"\" class=\"wp-block-prismatic-blocks\"><code class=\"language-\">Pop \u2192 C\nPop \u2192 B\nPop \u2192 A<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Core Stack Operations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A stack usually exposes a very small API, and we will keep the operations to just these to make our lives easy:<\/p>\n\n\n\n<pre data-line=\"\" class=\"wp-block-prismatic-blocks\"><code class=\"language-\">push()      \/\/ Add item to top\npop()       \/\/ Remove item from top\npeek()      \/\/ Read top without removing\nis_empty()  \/\/ Check if stack is empty<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Notice something important here:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A stack only ever interacts with <strong>one end<\/strong> of the structure \u2014 the top.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This turns out to matter a lot when choosing how to implement one. For the astute among you, you can probably see where we are going with this given our last few posts. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Why Stacks Matter in Real Systems<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Stacks show up everywhere:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u2022 Function call stacks<br>\u2022 Undo\/redo systems<br>\u2022 Expression parsing<br>\u2022 DFS graph traversal<br>\u2022 Embedded buffering patterns<br>\u2022 Temporary working memory in algorithms<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Performance First \u2014 Benchmarking the Implementation<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Before we talk about how this stack is implemented, let\u2019s look at real performance numbers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These benchmarks are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>push<\/li>\n\n\n\n<li>peek<\/li>\n\n\n\n<li>pop<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Each push allocates memory.<br>Each pop frees memory.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is the \u201chonest\u201d cost of dynamic allocation, and this performance readout follows the same general structure as the ones in our last posts: <\/p>\n\n\n\n<pre data-line=\"\" class=\"wp-block-prismatic-blocks\"><code class=\"language-\">=== Stack (L****d L**t) Benchmark ===\nReal implementation timing (includes malloc\/free)\n\n=============================\nBENCH N=1000\n=============================\npush         O(1)\/op total O(N)   |      0.031 ms |       30.9 ns\/op\npeek         O(1)\/op              |      0.987 ms |        0.5 ns\/op (REPS=2000000)\npop          O(1)\/op (+free)      |      0.008 ms |        8.3 ns\/op\n\n=============================\nBENCH N=3000\n=============================\npush         O(1)\/op total O(N)   |      0.089 ms |       29.6 ns\/op\npeek         O(1)\/op              |      1.112 ms |        0.6 ns\/op (REPS=2000000)\npop          O(1)\/op (+free)      |      0.026 ms |        8.7 ns\/op\n\n=============================\nBENCH N=10000\n=============================\npush         O(1)\/op total O(N)   |      0.272 ms |       27.2 ns\/op\npeek         O(1)\/op              |      1.023 ms |        0.5 ns\/op (REPS=2000000)\npop          O(1)\/op (+free)      |      0.087 ms |        8.7 ns\/op\n\n=============================\nBENCH N=30000\n=============================\npush         O(1)\/op total O(N)   |      0.699 ms |       23.3 ns\/op\npeek         O(1)\/op              |      0.939 ms |        0.5 ns\/op (REPS=2000000)\npop          O(1)\/op (+free)      |      0.235 ms |        7.8 ns\/op\n\n=============================\nBENCH N=100000\n=============================\npush         O(1)\/op total O(N)   |      2.360 ms |       23.6 ns\/op\npeek         O(1)\/op              |      0.935 ms |        0.5 ns\/op (REPS=2000000)\npop          O(1)\/op (+free)      |      0.786 ms |        7.9 ns\/op\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ignore the censored part of the metrics \ud83d\ude42<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The key takeaways:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Operation<\/th><th>Complexity<\/th><\/tr><\/thead><tbody><tr><td>push<\/td><td>O(1)<\/td><\/tr><tr><td>pop<\/td><td>O(1)<\/td><\/tr><tr><td>peek<\/td><td>O(1)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This is exactly what we want from a stack, and it is also identical to the previous charts for our tailless, tailed, and doubly linked list implementations. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">The Important Engineering Idea<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Here\u2019s the key concept for this post:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">A data structure is defined by its behavior and guarantees \u2014 not by how it is stored internally.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">If another structure already provides the complexity guarantees we need\u2026<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can reuse it.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Surprise! \u2014 The Stack Is Just Our Linked List!<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">This entire stack implementation is built on top of our <strong>tailless singly linked list<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">No new node structures.<br>No new memory management.<br>No new traversal logic.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Just restricted access.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Mapping Stack Operations \u2192 Linked List Operations<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Stack<\/th><th>Linked List<\/th><\/tr><\/thead><tbody><tr><td>push<\/td><td>push_front<\/td><\/tr><tr><td>pop<\/td><td>pop_front<\/td><\/tr><tr><td>peek<\/td><td>front<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">That\u2019s it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A stack is literally:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">A linked list where you are only allowed to touch the head.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Because of this, our tailless linked list fits the bill perfectly. Here is ALL the code for your reference:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>stack.h<\/strong><\/p>\n\n\n\n<pre data-line=\"\" class=\"wp-block-prismatic-blocks\"><code class=\"language-c\">#ifndef STACK_H\n#define STACK_H\n\n#include &quot;linked_list.h&quot;\n\n\/\/ our stack is literally just wrapping our tailless linked list\nstruct Stack {\n        struct Node* head;\n        size_t size;\n};\n\nvoid stack_init(struct Stack* s);\nvoid stack_destroy(struct Stack* s);\n\nint stack_push(struct Stack* s, struct Node* n);\nint stack_pop(struct Stack* s);\nstruct Node* stack_peek(const struct Stack* s);\n\nint stack_is_empty(const struct Stack* s);\nsize_t stack_size(const struct Stack* s);\n\n#endif<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>stack.c<\/strong><\/p>\n\n\n\n<pre data-line=\"\" class=\"wp-block-prismatic-blocks\"><code class=\"language-c\">#include &quot;stack.h&quot;\n\nvoid stack_init(struct Stack* s) {\n        if (!s) return;\n        s-&gt;head = NULL;\n        s-&gt;size = 0;\n}\n\nvoid stack_destroy(struct Stack* s) {\n        if (!s) return;\n        list_destroy(&amp;s-&gt;head); \/\/ uses linked_list.c\n        s-&gt;size = 0;\n}\n\nint stack_push(struct Stack* s, struct Node* n) {\n        if (!s || !n) return -1;\n        push_front(n, &amp;s-&gt;head); \/\/ uses linked_list.c\n        s-&gt;size++;\n        return 0;\n}\n\nint stack_pop(struct Stack* s) {\n        if (!s || !s-&gt;head) return -1;\n        pop_front(&amp;s-&gt;head); \/\/ uses linked_list.c (and frees node)\n        s-&gt;size--;\n        return 0;\n}\n\nstruct Node* stack_peek(const struct Stack* s) {\n        if (!s) return NULL;\n        return front(s-&gt;head); \/\/ uses linked_list.c\n}\n\nint stack_is_empty(const struct Stack* s) {\n        return (!s || s-&gt;head == NULL);\n}\n\nsize_t stack_size(const struct Stack* s) {\n        return s ? s-&gt;size : 0;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And for the code we reference in the above files, you can simply visit my post on <a href=\"https:\/\/mattbick.dev\/?p=66\" data-type=\"post\" data-id=\"66\">tailless linked lists<\/a>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So, did I cheat for today by using a bunch of code I already wrote? Kind of. However, later on, I promise it will all make sense when we eventually revisit some of these data structures in the future, but that is far, far away.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Over the last three posts, we created a tailless linked list, extended it into a tailed list, and finally we implemented a double linked list that solved the O(n) complexity hurdles. Each step added speed, but with that came some tradeoffs along with complexity. For Day 4, I have decided that the next logical step [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-83","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/mattbick.dev\/index.php?rest_route=\/wp\/v2\/posts\/83","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mattbick.dev\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mattbick.dev\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mattbick.dev\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mattbick.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=83"}],"version-history":[{"count":2,"href":"https:\/\/mattbick.dev\/index.php?rest_route=\/wp\/v2\/posts\/83\/revisions"}],"predecessor-version":[{"id":85,"href":"https:\/\/mattbick.dev\/index.php?rest_route=\/wp\/v2\/posts\/83\/revisions\/85"}],"wp:attachment":[{"href":"https:\/\/mattbick.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=83"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mattbick.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=83"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mattbick.dev\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=83"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}