How to implement 3 stacks with one array?

后端 未结 19 2271
迷失自我
迷失自我 2021-01-29 18:44

Sometimes, I come across the following interview question: How to implement 3 stacks with one array ? Of course, any static allocation is not a solution.

19条回答
  •  野的像风
    2021-01-29 19:07

    There are many solutions to this problem already stated on this page. The fundamental questions, IMHO are:

    • How long does each push/pop operation take?

    • How much space is used? Specifically, what is the smallest number of elements that can be pushed to the three stacks to cause the data structure to run out of space?

    As far as I can tell, each solution already posted on this page either can take up to linear time for a push/pop or can run out of space with a linear number of spaces still empty.

    In this post, I will reference solutions that perform much better, and I will present the simplest one.


    In order to describe the solution space more carefully, I will refer to two functions of a data structure in the following way:

    A structure that takes O(f(n)) amortized time to perform a push/pop and does not run out of space unless the three stacks hold at least n - O(g(n)) items will be referred to as an (f,g) structure. Smaller f and g are better. Every structure already posted on this page has n for either the time or the space. I will demonstrate a (1,√n) structure.

    This is all based on:

    • Michael L. Fredman and Deborah L. Goldsmith, "Three Stacks", in Journal of Algorithms, Volume 17, Issue 1, July 1994, Pages 45-70

      • An earlier version appeared in the 29th Annual Symposium on Foundations of Computer Science (FOCS) in 1988
    • Deborah Louise Goldsmith's PhD thesis from University of California, San Diego, Department of Electrical Engineering/Computer Science in 1987, "Efficient memory management for >= 3 stacks"

    They show, though I will not present, a (log n/log S,S) structure for any S. This is equivalent to a (t, n1/t) structure for any t. I will show a simplified version that is a (1,√n) structure.


    Divide the array up into blocks of size Θ(√n). The blocks are numbered from 1 to Θ(√n), and the number of a block is called its "address". An address can be stored in an array slot instead of a real item. An item within a given block can be referred to with a number less than O(√n), and such a number is called an index. An index will also fit in an array slot.

    The first block will be set aside for storing addresses and indexes, and no other block will store any addresses or indexes. The first block is called the directory. Every non-directory block will either be empty or hold elements from just one of the three stacks; that is, no block will have two elements from different stacks. Additionally, every stack will have at most one block that is partially filled -- all other blocks associated with a stack will be completely full or completely empty.

    As long as there is an empty block, a push operation will be permitted to any stack. Pop operations are always permitted. When a push operation fails, the data structure is full. At that point, the number of slots not containing elements from one of the stacks is at most O(√n): two partially-filled blocks from the stacks not being pushed to, and one directory block.

    Every block is ordered so that the elements closer to the front of the block (lower indexes) are closer to the bottom of the stack.

    The directory holds:

    • Three addresses for the blocks at the top of the three stacks, or 0 if there are no blocks in a particular stack yet

    • Three indexes for the element at the top of the three stacks, or 0 if there are no items in a particular stack yet.

    • For each full or partially full block, the address of the block lower than it in the same stack, or 0 if it is the lowest block in the stack.

    • The address of a free block, called the leader block, or 0 if there are no free blocks

    • For each free block, the address of another free block, or 0 if there are no more free blocks

    These last two constitute a stack, stored as a singly-linked list, of free blocks. That is, following the addresses of free blocks starting with the leader block will give a path through all the free blocks, ending in a 0.

    To push an item onto a stack, find its top block and top element within that block using the directory. If there is room in that block, put the item there and return.

    Otherwise, pop the stack of free blocks by changing the address of the leader block to the address of the next free block in the free block stack. Change the address and index for the stack to be the address of the just-popped free block and 1, respectively. Add the item to the just-popped block at index 1, and return.

    All operations take O(1) time. Pop is symmetric.

提交回复
热议问题