我有一个功能齐全的快速排序分区算法,我正在努力适应每个比较的计数器。这给了我一个挑战。关于把这个计数器放在哪里的任何提示?
def partition(mylist, start, end):
pos = start
for i in range(start, end):
if mylist[i] < mylist[end]:
mylist[i],mylist[pos] = mylist[pos],mylist[i]
pos += 1
mylist[pos],mylist[end] = mylist[end],mylist[pos]
return pos
def quicksort(mylist, start, end, c):
if start < end:
pos = partition(mylist, start, end)
c= c+ (len(mylist) -1 )
quicksort(mylist, start, pos - 1, c)
c= c+ (len(mylist) -1 )
quicksort(mylist, pos + 1, end, c)
c= c+ (len(mylist) -1 )
count = (0)
quicksort(x, 0, len(x)-1, count)
x
指的是整数列表
答案 0 :(得分:0)
您只有两个显式比较发生的地方,两个都是if语句,您可以在这些行之前放置一个计数器增量,例如:
counter = 0 # the global variable
def myfunc1():
global counter
counter = counter + 1
if my < comparison:
pass
def myfunc2():
global counter
counter = counter + 1
if my < comparison:
pass
print(counter)
例如,这并不计算for循环机制中的隐式比较,但我认为这不是你想要做的。
这是另一种可以传递计数器信息的可爱方式,并避免全局:
def myfunc1():
myfunc1.counter += 1
if 2 < 1:
pass
def myfunc2():
myfunc2.counter += 1
if 1 < 2:
pass
myfunc1.counter = 0
myfunc2.counter = 0
for f in (myfunc1, myfunc2):
print("{} had {} comparisons".format(f.__name__, f.counter))
编辑/注意:这里的一些答案使用传递到每个函数的参数来跟踪计数器。这也是一种有效的方法,但实际上我们需要的是一种更通用的方法(否则你会无休止地在一般情况下绕过计数器,这很痛苦)。总结:
请注意,这使用装饰器,这意味着您可以添加任意数量的函数,例如less_than,而不会让他们理解计数要求。
def count(func):
def inner(*args):
inner.counter += 1
return func(*args)
inner.counter = 0
return inner
@count
def less_than(op1, op2):
return op1 < op2
def partition(mylist, start, end):
pos = start
for i in range(start, end):
if less_than(mylist[i], mylist[end]):
mylist[i],mylist[pos] = mylist[pos],mylist[i]
pos += 1
mylist[pos],mylist[end] = mylist[end],mylist[pos]
return pos
def quicksort(mylist, start, end):
if less_than(start, end):
pos = partition(mylist, start, end)
quicksort(mylist, start, pos - 1)
quicksort(mylist, pos + 1, end)
x = [3, 2, 5, 1, 0]
quicksort(x, 0, len(x)-1)
print(x)
print(less_than.counter)
您可以通过创建一个计数器类来进一步组织它,该计数器类跟踪任何数量的函数以及它们被调用的所有时间,并删除函数属性,将数据存储在例如。字典。
答案 1 :(得分:0)
def partition(mylist, start, end, count):
pos = start
for i in range(start, end):
count += 1
if mylist[i] < mylist[end]:
mylist[i],mylist[pos] = mylist[pos],mylist[i]
pos += 1
mylist[pos],mylist[end] = mylist[end],mylist[pos]
return pos, count
def quicksort(mylist, start, end, count):
if start < end:
pos, count = partition(mylist, start, end, count)
count = quicksort(mylist, start, pos - 1, count)
count = quicksort(mylist, pos + 1, end, count)
return count
x = [2,3,1]
count = quicksort(x, 0, len(x)-1, 0)
print x, count
答案 2 :(得分:0)
要进一步改进一些现有的答案,除非你试图使这个尾部递归(这对于快速排序不起作用),你不需要传递计数值。相反,您可以只维护每个对分区的调用返回其已执行的所有比较的计数的不变量,并且每次调用quicksort都会返回由它执行的所有分区的计数或其中的任何递归调用。
此外,我们可以将quicksort的递归实现放入一个辅助函数中并将其包装在一个很好的函数中,该函数只需要一个列表,因此我们不必手动传入开始和结束索引。
实现这一点为我们提供了以下内容:
def _partition(mylist, start, end):
count = 0
pos = start
for i in xrange(start, end):
count += 1
if mylist[i] < mylist[end]:
mylist[i], mylist[pos] = mylist[pos], mylist[i]
pos += 1
mylist[pos], mylist[end] = mylist[end], mylist[pos]
return pos, count
def _quicksort(mylist, start, end):
count = 0
if start < end:
pos, count = _partition(mylist, start, end)
count += _quicksort(mylist, start, pos - 1)
count += _quicksort(mylist, pos + 1, end)
return count
def quicksort(mylist, start=None, end=None):
if start is None:
start = 0
if end is None:
end = len(mylist) - 1
return _quicksort(mylist, start, end)
x = [2,3,1]
count = quicksort(x)
print x, count