17.15 Implementing a First-In First-Out Container


Credit: Sébastien Keim

17.15.1 Problem

You need a container that allows element insertion and removal, in which the first element inserted is also the first to be removed (i.e., a first-in first-out, FIFO, queue).

17.15.2 Solution

We can use a class to wrap a Pythonic implementation of a linked list:

class Fifo:     def _ _init_ _(self):         self.first = None         self.last = None     def append(self, data):         node = [data, None]  # [payload, 'pointer'] "pair"         if self.first is None:             self.first = node         else:             self.last[1] = node         self.last = node     def pop(self):         if self.first is None :             raise IndexError         node = self.first         self.first = node[1]         return node[0] if _ _name_ _=='_ _main_ _':  # Run a test/example when run as a script:     a = Fifo(  )     a.append(10)     a.append(20)     print a.pop(0)     a.append(5)     print a.pop(0)     print a.pop(0)

17.15.3 Discussion

Most likely, the best way to do a FIFO in Python is to use standard lists with append and pop(0) methods. Since lists are built-ins, they are usually far more efficient than this recipe, despite theoretical considerations of O(1) versus O(N) performance. If you want to try this, it's easy:

class FifoList:     def _ _init_ _(self):         self.data = []     def append(self, data):         self.data.append(data)     def pop(self):         return self.data.pop(0)

A quirky variation that ensures O(1) performance can be built on top of a dictionary:

class FifoList:     def _ _init_ _(self):         self.data = {}         self.nextin = 0         self.nextout = 0     def append(self, data):         self.nextin += 1         self.data[self.nextin] = data     def pop(self):         self.nextout += 1         result = self.data[self.nextout]         del self.data[self.nextout]         return result

I developed this recipe after I read an academic paper that said that double-linked lists were the natural way to create this kind of container (in contrast with stacks). I convinced myself that it was possible and quite natural to create a FIFO container with single-linked lists, instead. It suffices to have two references to first and last in the Fifo class itself. The class in the recipe's solution shows one way to build a single-linked list in Python via pairs that reference the actual data (also known as the payload) as their first item and use the second item to refer to another such pair (None being used as a null pointer here).

The append method builds such a pair (actually a two-item list) and threads it onto the list, altering the first and last attributes of self appropriately. The popmethod unthreads the node at the head of the list in a similar but mirrored way.



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2005
Pages: 346

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net