- push(): push into current stack. If current stack is full, borrow from neighbor (which, if full, borrows from its neighbor and so on recursively) and push. If all stacks are full, throw.
- move(): If the stack has space, shift its elements to right and lend. If not, check its neighbor. When all stacks are full, the calls will loop around to same stack. So note the first stack that calls move(). Adjust top and capacity here.
- shift: shift elements to right and wrap around.
- pop(): Typical. No adjusting here.
Note:
It is better that move() returns false and push() throws "stacks full" instead of move() throwing. The exception stack would be cluttered if move() throws as it would throw after looping back. stack-combined could throw in its push() by keeping its own count but then logic is in different classes and stack is not whole.
stack: a id top // no need to track start capacity count stack neighbor stack(a, id, top, capacity): a = a id = id top = top capacity = capacity count = 0 // push into current or borrow from neighbor and push push(T x): if count < capacity: push_(x) else if neighbor.move(id): capacity++ push_(x) else: throw "stacks full" push_(T x): a[top] = x // last stack overflows into first top = mod(top+1, a.length()) count++ // check current stack and then neighbor bool move(id): // all stacks are full and back to same stack if id == this.id: return false if count < capacity: shift() top = mod(top+1, a.length()) capacity-- return true if neighbor.move(id): shift() top = mod(top+1, a.length()) return true return false // move elements to right shift(): i = top for c = 0, c < count, c++: // wrap around, so a[i] = a[i-1] except a[0] = a[last] previ = mod(i-1, a.length()) a[i] = a[previ] i = previ // clear for clarity a[i] = null T pop(): if count == 0: throw "stack {id} empty" count-- top = mod(top-1, a.length()) t = a[top] // clear for clarity a[top] = null return t mod(x, n): m = x % n if m < 0: m += n return m // n stacks with capacity capacity stack-combined: stack-combined(n, capacity): // assume equal capacity for all a = new [size *n] stacks = new stack[n] for i = 0, i < n, i++: stacks[i] = new stack(a, id: i, top: capacity*i, capacity) // 0's neighbor is 1, (n-1)'s is 0 for i = 0, i < n, i++: stacks[i].neighbor = stack[mod(i+1, n)] push(id, x): if !(0 <= id < n): throw stacks[id].push(x) pop(id): if !(0 <= id < n): throw stacks[id].pop()
[Hat tip to ctci]
No comments:
Post a Comment