How to implement 3 stacks with one array?

后端 未结 19 2266
迷失自我
迷失自我 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:06

    Maintain a single arena for all three stacks. Each element pushed onto the stack has a backwards pointer to its previous element. The bottom of each stack has a pointer to NULL/None.

    The arena maintains a pointer to the next item in the free space. A push adds this element to the respective stack and marks it as no longer in the free space. A pop removes the element from the respective stack and adds it to the free list.

    From this sketch, elements in stacks need a reverse pointer and space for the data. Elements in the free space need two pointers, so the free space is implemented as a doubly linked list.

    The object containing the three stacks needs a pointer to the top of each stack plus a pointer to the head of the free list.

    This data structure uses all the space and pushes and pops in constant time. There is overhead of a single pointer for all data elements in a stack and the free list elements use the maximum of (two pointers, one pointer + one element).


    Later: python code goes something like this. Note use of integer indexes as pointers.

    class StackContainer(object):
        def __init__(self, stack_count=3, size=256):
            self.stack_count = stack_count
            self.stack_top = [None] * stack_count
            self.size = size
            # Create arena of doubly linked list
            self.arena = [{'prev': x-1, 'next': x+1} for x in range(self.size)]
            self.arena[0]['prev'] = None
            self.arena[self.size-1]['next'] = None
            self.arena_head = 0
    
        def _allocate(self):
            new_pos = self.arena_head
            free = self.arena[new_pos]
            next = free['next']
            if next:
                self.arena[next]['prev'] = None
                self.arena_head = next
            else:
                self.arena_head = None
            return new_pos
    
        def _dump(self, stack_num):
            assert 0 <= stack_num < self.stack_count
            curr = self.stack_top[stack_num]
            while curr is not None:
                d = self.arena[curr]
                print '\t', curr, d
                curr = d['prev']
    
        def _dump_all(self):
            print '-' * 30
            for i in range(self.stack_count):
                print "Stack %d" % i
                self._dump(i)
    
        def _dump_arena(self):
            print "Dump arena"
            curr = self.arena_head
            while curr is not None:
                d = self.arena[curr]
                print '\t', d
                curr = d['next']
    
        def push(self, stack_num, value):
            assert 0 <= stack_num < self.stack_count
            # Find space in arena for new value, update pointers
            new_pos = self._allocate()
            # Put value-to-push into a stack element
            d = {'value': value, 'prev': self.stack_top[stack_num], 'pos': new_pos}
            self.arena[new_pos] = d
            self.stack_top[stack_num] = new_pos
    
        def pop(self, stack_num):
            assert 0 <= stack_num < self.stack_count
            top = self.stack_top[stack_num]
            d = self.arena[top]
            assert d['pos'] == top
            self.stack_top[stack_num] = d['prev']
            arena_elem = {'prev': None, 'next': self.arena_head}
            # Link the current head to the new head
            head = self.arena[self.arena_head]
            head['prev'] = top
            # Set the curr_pos to be the new head
            self.arena[top] = arena_elem
            self.arena_head = top
            return d['value']
    
    if __name__ == '__main__':
        sc = StackContainer(3, 10)
        sc._dump_arena()
        sc.push(0, 'First')
        sc._dump_all()
        sc.push(0, 'Second')
        sc.push(0, 'Third')
        sc._dump_all()
        sc.push(1, 'Fourth')
        sc._dump_all()
        print sc.pop(0)
        sc._dump_all()
        print sc.pop(1)
        sc._dump_all()
    

提交回复
热议问题