【问题标题】:Counting comparisons quicksort without global Python在没有全局 Python 的情况下计算比较快速排序
【发布时间】:2014-11-06 00:06:45
【问题描述】:

我有一个运行良好的快速排序和计数比较代码。但是每次我调用该函数时,计数都会一次又一次地累加。有什么办法可以避免吗?

count = 0
def quicksort(A, left = None, right =None):
    global count
    if left is None:
        left = 0
    if right is None:
        right = len(A)
    if left >= right:
        return
    p =A[left]

    i = left +1
    for j in range(left+1,right):
        if A[j] < p:
            A[i] , A[j] = A[j], A[i]
            i = i + 1
    A[left] , A[i-1] = A[i-1], A[left]
    quicksort(A,left,i-1)
    count += i-1-left
    quicksort(A,i,right)
    count += right-i-1

    return A,count+len(A)

【问题讨论】:

  • 这正是你要求它做的;你永远不会重置count = 0
  • 如果,具体来说,如果您希望此快速排序实现对比较进行计数,请考虑将其计算为返回值
  • @jonrsharpe 如果我删除 count=0,我得到一个错误 global name count is not defined。
  • @user3332615 ...当然,因为它没有定义;我在哪里建议你应该删除它?
  • @SimeonVisser 你能告诉我如何使用返回值进行计算吗?我是编码新手。

标签: python python-3.x global-variables quicksort


【解决方案1】:

为了使其与全局count 一起工作,您需要在第一级递归处重置它。一种方法是将您的实现移动到一个单独的函数_quicksort 以递归方式调用自身,并在调用之前重置计数器:

def quicksort(A):
    global count
    count = 0
    return _quicksort(A)

def _quicksort(A, left=None, right=None):
    global count
    ...
    _quicksort(A,left,i-1)
    ...

此外,这还简化了您的主函数签名,因为quicksort 最终用户并不真正需要了解leftright

现在,最好不要使用全局变量,因为这是一种不好的做法。然后,您需要以某种方式将上下文传递给_quicksort 函数,以便它知道要处理哪个计数器。所以你需要传递一些东西作为参数:

def _quicksort(context, A, left=None, right=None):
    ...
    _quicksort(context, ...)

例如,这个context 可以是像{'count': 0} 这样的字典,然后您可以将其作为context['count'] 访问,或者它可以是使用context.count 的对象。请注意,在这种情况下,这非常接近类,其中上下文是对象本身,_quicksort 将是一个类方法:

class _Quicksort(object):
    count = 0
    def _quicksort(self, A, left=None, right=None):
        ...
        self._quicksort(A, ...)
        self.count += ...

最后,在递归函数中处理上下文的另一种常用方法是“按值”传递和返回变量,例如:

def _quicksort(count, other_context, A, left=None, right=None):
    ...
    count1, other_context1 = _quicksort(count, other_context, A, left, right)
    ...
    return count + count1, other_context

但是你最终会得到一个杂乱的方法签名,并且必须弄清楚count在这种情况下的含义以及如何获得相同的结果(这是一个很好的练习!)。

【讨论】:

  • 感谢您对不同实现方式的详细解释。我了解重置计数器。我最近开始编码,所以我对课程不太了解,但之后我真的对学习很感兴趣。
  • @user3332615,很高兴为您提供帮助!您应该尽可能避免使用全局状态,并且类通过创建可以使用的局部上下文而不是全局变量来帮助您。如果您好奇的话,这个 Python 类介绍看起来是一个很好的起点:jesshamrick.com/2011/05/18/…
猜你喜欢
  • 2014-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-21
  • 1970-01-01
  • 1970-01-01
  • 2017-01-30
相关资源
最近更新 更多