import collections
import time
# Requires Python 2.7
class Node(object):
def __init__(self, value):
self.value = value
self.next = None
self.prev = None
def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, self.value)
class LinkedList(collections.MutableSequence):
def __init__(self, iterable=None):
self.sentinel = Node(None)
self.sentinel.next = self.sentinel
self.sentinel.prev = self.sentinel
self.__len = 0
if iterable is not None:
self += iterable
def get_node(self, index):
node = sentinel = self.sentinel
i = 0
while i <= index:
node = node.next
if node == sentinel:
break
i += 1
if node == sentinel:
node = None
return node
def __getitem__(self, index):
node = self.__get_node(index)
return node.value
def __len__(self):
return self.__len
def __setitem__(self, index, value):
node = self.get_node(index)
node.value = value
def __delitem__(self, index):
node = self.get_node(index)
if node:
node.prev.next = node.next
if node.next:
node.next.prev = node.prev
node.prev = None
node.next = None
node.value = None
self.__len -= 1
def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
list_ = [self.__get_node(i).value for i in range(len(self))]
return '%s(%r)' % (self.__class__.__name__, list_)
def append(self, value):
sentinel = self.sentinel
node = Node(value)
self.insert_between(node, sentinel.prev, sentinel)
def insert(self, index, value):
sentinel = self.sentinel
new_node = Node(value)
len_ = len(self)
if len_ == 0:
self.insert_between(new_node, sentinel, sentinel)
elif index >= 0 and index < len_:
node = self.get_node(index)
self.insert_between(new_node, node.prev, node)
elif index == len_:
self.insert_between(new_node, sentinel.prev, sentinel)
else:
raise IndexError
self.__len += 1
def insert_between(self, node, left_node, right_node):
if node and left_node and right_node:
node.prev = left_node
node.next = right_node
left_node.next = node
right_node.prev = node
else:
raise IndexError
class Stopwatch(object):
def __init__(self):
self.__start = 0.0
self.__stop = 0.0
self.__duration = 0.0
def start(self):
self.__start = time.time()
return self
def stop(self):
self.__stop = time.time()
self.__duration = self.__stop - self.__start
return self.__duration
def duration(self):
return self.__duration
class Profiler(object):
def __init__(self, size):
self.size = size
self.list = None
self.linked_list = None
self.sw_create_list = Stopwatch()
self.sw_create_linked_list = Stopwatch()
self.sw_pop_list = Stopwatch()
self.sw_pop_linked_list = Stopwatch()
def create_list(self):
self.sw_create_list.start()
self.list = [i for i in range(self.size)]
self.sw_create_list.stop()
def create_linked_list(self):
self.sw_create_linked_list.start()
self.linked_list = LinkedList()
for value in self.list:
self.linked_list.append(value)
self.sw_create_linked_list.stop()
def pop_list(self):
self.sw_pop_list.start()
for i in range(self.size):
del self.list[0]
self.sw_pop_list.stop()
def pop_linked_list(self):
self.sw_pop_linked_list.start()
for i in range(self.size):
del self.linked_list[0]
self.sw_pop_linked_list.stop()
def report(self):
print("%6s %10d" % ("Size", self.size))
print("%6s %10s %10s %10s" % ("Type", "Create", "Pop", "Total"))
print("%6s %10.2f %10.2f %10.2f" % ("List", self.sw_create_list.duration(), \
self.sw_pop_list.duration(), self.sw_create_list.duration() + self.sw_pop_list.duration()))
print("%6s %10.2f %10.2f %10.2f" % ("Linked", self.sw_create_linked_list.duration(), \
self.sw_pop_linked_list.duration(), self.sw_create_linked_list.duration() + \
self.sw_pop_linked_list.duration()))
print
def run(self):
self.create_list()
self.pop_list()
self.create_linked_list()
self.pop_linked_list()
self.report()
if __name__ == '__main__':
Profiler(1000).run()
Profiler(2000).run()
Profiler(5000).run()
Profiler(10000).run()
Profiler(20000).run()
Profiler(50000).run()
Profiler(100000).run()
print "Complete."