我正致力于使用算法和数据结构解决问题并遇到这个问题:设计并实现一个实验,将Python列表的性能与作为链接列表实现的列表进行比较。
以下是我的链接列表实现。
class Node(object):
def __init__(self, data):
self.data = data
self.next = None
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self, new_data):
self.data = new_data
def set_next(self, new_next):
self.next = new_next
class UnOrderedList(object):
def __init__(self):
self.N = 0
self.head = None
def size(self):
return self.N
def is_empty(self):
return self.N == 0
def add(self, data):
self.N += 1
temp = Node(data)
temp.set_next(self.head)
self.head = temp
def search(self, data):
current = self.head
found = False
while current and not found:
if current.get_data() == data:
found = True
current = current.get_next()
return found
def remove(self, item):
current = self.head
previous = None
while current.get_data() != item:
previous = current
current = current.get_next()
if not previous:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
self.N -= 1
测试删除方法:
for i in range(1000, 100000001, 100000):
list1 = list(range(i))
list2 = UnOrderedList()
for a in range(i):
list2.add(a)
a = random.randrange(0, i)
start_time1 = time.time()
list1.remove(a)
end_time1 = time.time()
start_time2 = time.time()
list2.remove(a)
end_time2 = time.time()
print("List time: {0}. Linked List time: {1}".format(end_time1-start_time1, end_time2-start_time2))
对于我的测试,我使用python list的类似方法测试链表的方法,链表总是很短。所以我在互联网上读了一下,发现虽然python列表在索引/搜索方面更好,但链表应该在添加或删除时胜过它。
所以我的问题是,链表总是慢于列表或我做错了什么?
答案 0 :(得分:3)
其他答案已经跳过了一个非常重要的细节,只有当要删除的节点的指针作为参数而不是节点的值提供时,链表才会优于remove()方法中的数组。
否则,您将不得不搜索列表,该列表与从基于索引的列表中删除元素具有相同的O(n)复杂性。
但这里有另一个稍微不那么重要的因素。 Python列表实际上是用C语言实现的。纯Python程序不太可能胜过C语言,特别是当专家多年来编写和优化时。
答案 1 :(得分:1)
Python列表是从数组实现的。因此,您要将链接列表与数组进行比较。
在链接列表中,您可以轻松插入/删除元素,但是在插入/删除元素后,在数组中移动其他元素需要更多时间。
有关详细信息,请参阅array and linkedlist之间的比较。此quora question解释了python中列表的实现。
答案 2 :(得分:1)
你的测试没有测试链表有优势的东西。这是一个测试的地方:
>>> from timeit import timeit
>>> linked_list = UnOrderedList()
>>> timeit(lambda: linked_list.add(0), number=10**5)
0.08297442221169149
>>> python_list = []
>>> timeit(lambda: python_list.insert(0, 0), number=10**5)
1.5988611595369093
或者您可以使用自己的测试但不将a
设置为随机值(即将其保持在i-1
):
List time: 0.0. Linked List time: 0.0
List time: 0.00100016593933. Linked List time: 0.0
List time: 0.00200009346008. Linked List time: 0.0
List time: 0.00300002098083. Linked List time: 0.0
List time: 0.00300002098083. Linked List time: 0.0
List time: 0.00399994850159. Linked List time: 0.0
List time: 0.00499987602234. Linked List time: 0.0
List time: 0.00699996948242. Linked List time: 0.0
List time: 0.00699996948242. Linked List time: 0.0
List time: 0.00799989700317. Linked List time: 0.0
List time: 0.00999999046326. Linked List time: 0.0
List time: 0.00899982452393. Linked List time: 0.0
...
答案 3 :(得分:0)
由于以下原因,您的链接列表将始终较慢:
-Python list在C(基于数组)中实现,总是会更好地执行
- 你的实现是在python中使用间接,它的速度较慢。
答案 4 :(得分:0)
Python的列表基于C数组。在迭代和随机访问期间,数组优于链表,而链表在随机插入和删除方面具有优势。
This详细介绍了两者之间的理论差异。