Chapter 3 Stacks and Queues - 3.1

来源:互联网 发布:淘宝上开店 编辑:程序博客网 时间:2024/05/21 16:48
Problem 3.1: Describe how you could use a single array to implement three stacks.

Splitting the array into three individual parts is quite intuitive.

How can we take full advantage of the unused space? I was inspired by the implementation of circular queue. Actually, in my perspective, my solution is better than the one on answer page. The idea is not complicated: When there is no free space next to top of the stack, into which we want to push a value, I shift other stacks to make a free space available for the stack.

It takes me more than two hours to implement the class. Thanks to work break down method, I encapsulated some work into utility functions and made the implementation quite smooth.
class n_stacks:    def __init__(self, stacks_num, array_size):        if array_size < stacks_num:            print "array_size is too small"            return        self.stacks_num = stacks_num        self.array = [None for i in range(0, array_size)]        size_per_stack = int(array_size/stacks_num)        self.tops = [size_per_stack*i for i in range(0, self.stacks_num)]        self.bottoms = self.tops[:]    def push(self, stack_no, value):        next_stack_no = next_in_circle(stack_no, self.stacks_num)        # If there is no room between given stack and the next stack        if self.tops[stack_no] == self.bottoms[next_stack_no]:            # If failed to make room            if not self.make_room_for(stack_no):                return False        # If we can come here, there is some room available        self.array[self.tops[stack_no]] = value        self.tops[stack_no] = next_in_circle(self.tops[stack_no], len(self.array))        return True    def pop(self, stack_no):        # If there is no element in this stack        if self.tops[stack_no] == self.bottoms[stack_no]:            return None        self.tops[stack_no] = pre_in_circle(self.tops[stack_no], len(self.array))        return self.array[self.tops[stack_no]]    def length(self, stack_no):        if self.bottoms[stack_no] <= self.tops[stack_no]:            return (self.tops[stack_no] - self.bottoms[stack_no])        else:            return (len(self.array) - (self.bottoms[stack_no] - self.tops[stack_no]))     def make_room_for(self, stack_no):        # Iterate all stacks after the given one        # and try to find a free element between two of them        current_no = next_in_circle(stack_no, self.stacks_num)        while current_no != stack_no:            next_no = next_in_circle(current_no, self.stacks_num)            # If there is a free element between current stack and next one            if self.tops[current_no] != self.bottoms[next_no]:                # A stack occupies at least one element (even when it is empty)                # Whether there is a free element based on the additional condition above?                current_top_next = next_in_circle(self.tops[current_no], len(self.array))                if (current_top_next == self.bottoms[next_no]) and (self.tops[current_no] == self.bottoms[current_no]):                    # If there is no free element, continue                    pass                else:                    # If there is a free element, break and utilize the free element                    break            current_no = next_no        # If we did not find a free element        if current_no == stack_no:            return False        # If we find one, shift stacks to make the        # free element available for given stack        while current_no != stack_no:            self.shift_stack_forward(current_no)            current_no = pre_in_circle(current_no, self.stacks_num)        return True    def shift_stack_forward(self, stack_no):        # Shift all elements in the given stack         n = self.tops[stack_no]        while n != self.bottoms[stack_no]:            n_pre = pre_in_circle(n, len(self.array))            self.array[n] = self.array[n_pre]             n = n_pre        # Shift the top and bottom        self.tops[stack_no] = next_in_circle(self.tops[stack_no], len(self.array))        self.bottoms[stack_no] = next_in_circle(self.bottoms[stack_no], len(self.array))            # Utility function to get next index in a circledef next_in_circle(current, total):    return (current+1)%total# Utility function to get previous index in a circledef pre_in_circle(current, total):    result = current - 1    if result < 0:        return (total + result)    else:        return result

Here are the test cases:
from n_stacks import *if __name__ == "__main__":    triple_stacks = n_stacks(3, 9)    print "stack 0: length", triple_stacks.length(0)    print "stack 1: length", triple_stacks.length(1)    print "stack 2: length", triple_stacks.length(2)    print "stack 0: push 0", triple_stacks.push(0, 0)    print "stack 0: push 1", triple_stacks.push(0, 1)     print "stack 0: push 2", triple_stacks.push(0, 2)    print "stack 1: push 10", triple_stacks.push(1, 10)    print "stack 1: push 11", triple_stacks.push(1, 11)     print "stack 1: push 12", triple_stacks.push(1, 12)    print "stack 2: push 20", triple_stacks.push(2, 20)    print "stack 2: push 21", triple_stacks.push(2, 21)     print "stack 2: push 22", triple_stacks.push(2, 22)    print "stack 2: push 23", triple_stacks.push(2, 23)    print "stack 0: pop", triple_stacks.pop(0)    print "stack 2: push 23", triple_stacks.push(2, 23)    print "stack 2: push 24", triple_stacks.push(2, 24)    print "stack 1: pop", triple_stacks.pop(1)    print "stack 2: push 24", triple_stacks.push(2, 24)    print "stack 2: pop", triple_stacks.pop(2)    print "stack 2: pop", triple_stacks.pop(2)    print "stack 2: pop", triple_stacks.pop(2)    print "stack 2: pop", triple_stacks.pop(2)    print "stack 2: pop", triple_stacks.pop(2)    print "stack 2: pop", triple_stacks.pop(2)    print "stack 0: push 2", triple_stacks.push(0, 2)    print "stack 0: push 3", triple_stacks.push(0, 3)    print "stack 0: push 4", triple_stacks.push(0, 4)    print "stack 0: push 5", triple_stacks.push(0, 5)    print "stack 0: push 6", triple_stacks.push(0, 6)    print "stack 2: push 20", triple_stacks.push(2, 20)    print "stack 2: push 21", triple_stacks.push(2, 21)    print "stack 0: length", triple_stacks.length(0)    print "stack 1: length", triple_stacks.length(1)    print "stack 2: length", triple_stacks.length(2)    print "stack 0: pop", triple_stacks.pop(0)    print "stack 0: pop", triple_stacks.pop(0)    print "stack 0: pop", triple_stacks.pop(0)    print "stack 0: pop", triple_stacks.pop(0)    print "stack 0: pop", triple_stacks.pop(0)    print "stack 0: pop", triple_stacks.pop(0)    print "stack 0: pop", triple_stacks.pop(0)    print "stack 1: push 12", triple_stacks.push(1, 12)    print "stack 1: push 13", triple_stacks.push(1, 13)    print "stack 1: push 14", triple_stacks.push(1, 14)    print "stack 1: push 15", triple_stacks.push(1, 15)    print "stack 1: push 16", triple_stacks.push(1, 16)    print "stack 1: push 17", triple_stacks.push(1, 17)    print "stack 0: length", triple_stacks.length(0)    print "stack 1: length", triple_stacks.length(1)    print "stack 2: length", triple_stacks.length(2)    print "stack 1: pop", triple_stacks.pop(1)    print "stack 1: pop", triple_stacks.pop(1)    print "stack 1: pop", triple_stacks.pop(1)    print "stack 1: pop", triple_stacks.pop(1)    print "stack 1: pop", triple_stacks.pop(1)    print "stack 1: pop", triple_stacks.pop(1)    print "stack 1: pop", triple_stacks.pop(1)    print "stack 1: pop", triple_stacks.pop(1)    print "stack 0: length", triple_stacks.length(0)    print "stack 1: length", triple_stacks.length(1)    print "stack 2: length", triple_stacks.length(2)    print "stack 2: pop", triple_stacks.pop(2)    print "stack 2: pop", triple_stacks.pop(2)    print "stack 0: length", triple_stacks.length(0)    print "stack 1: length", triple_stacks.length(1)    print "stack 2: length", triple_stacks.length(2)


原创粉丝点击