所以我一直在努力保持一个列表的顺序。所以每当有新数据进来时,我都会把它插入到“排序列表”中。
问题,为什么 bisect.insort 比我的链表实现快得多。我知道二分搜索需要 O(logn),但由于插入到列表中,它确实需要 O(n)。其中链表实现也应该是 O(n)。在排序的链表中插入新值也应该是 O(n)。但是为什么时间比较慢得多?我的链表实现没有优化吗?
这是我的示例代码:
import timeit
import bisect
import random
# Testing parameters
NUM_ITERATION_TEST = 10
TOTAL_NUM_DATA = 10000
DATA = [random.randint(0, 1000) for x in range(TOTAL_NUM_DATA)]
class Node():
def __init__(self, val):
self.val = val
self.next = None
class LinkedListIterator():
def __init__(self, head):
self.current = head
def __iter__(self):
return self
def __next__(self):
if not self.current:
raise StopIteration
else:
val = self.current.val
self.current = self.current.next
return val
class LinkedList():
def __init__(self):
self.head = None
def __iter__(self):
return LinkedListIterator(self.head)
def insert(self, val):
new_node = Node(val)
if self.head is None:
self.head = new_node
return
curr = self.head
if curr.val > val:
new_node.next = curr
self.head = new_node
return
while curr.next:
if curr.next.val > val:
break
curr = curr.next
new_node.next = curr.next
curr.next = new_node
def method1(DATA):
sorted_list = []
for num in DATA:
bisect.insort_right(sorted_list, num)
def method2(DATA):
sorted_list = LinkedList()
for num in DATA:
sorted_list.insert(num)
if __name__ == "__main__":
# METHOD 1
print("Method 1 Execution Time:")
print(timeit.timeit("test_timeit.method1(test_timeit.DATA)",
number=NUM_ITERATION_TEST,
setup="import test_timeit"))
# METHOD 2
print("Method 2 Execution Time:")
print(timeit.timeit("test_timeit.method2(test_timeit.DATA)",
number=NUM_ITERATION_TEST,
setup="import test_timeit"))
执行时间为:
Method 1 Execution Time:
0.11593010000000001
Method 2 Execution Time:
33.0651346
我还尝试使用其他实现,例如排序的字典,但没有什么比 bisect 实现更好的了。有没有更有效的实现方式?基本上想要一个始终排序的数据列表,我会不断向列表中添加/插入新数据..