【问题标题】:Quick sort last step incorrect快速排序最后一步不正确
【发布时间】:2019-04-07 15:20:24
【问题描述】:

我正在为 Python 3.6 中的列表快速排序编写代码。

在每一步我都打印出 i 和 j 的值(我使用的两个变量)以及列表(还有正在交换的值)。代码工作正常,直到最后一步,即交换 40 和 50。放置 60 后,它不会进一步移动到最后一步(交换 40、50)。我不确定为什么会这样。在那之前,一切都很好。

** 自己尝试过自己写程序,所以请暂时忽略算法的效率(虽然,欢迎任何建议)

L=[35, 10, 40, 20, 60, 30, 90, 70, 50]

l=0
h=9

def partition (L, l, h):
    print("\n########## Partition() invoked: ",l,h)
    pivot = L[l]
    i = l
    j = h
    #print(i,j)
    while i<j:
        print(pivot, "***********", L)
        while True:
            i=i+1
            print("i=",i, L[i])
            if L[i]>pivot or i>=len(L):

                break
        while True:
            j=j-1
            print("j=",j, L[j])
            if L[j]<=pivot or j<0:
                break
        print("Check greater", i, j)
        if i>j:
            break
        print("Swapping: ",L[i],L[j])
        L[i], L[j] = L[j], L[i]

    print("l=", L[l], "  j=", L[j], L)
    j_val=L[j]
    l_val=L[l]
    L[l]=j_val
    L[j]=l_val
    print("l=", L[l], " j=", L[j] , l, j,  L)
    return i


def QuickSort( L, l, h):
    print(l, h)
    j = partition(L, l, h)
    partition(L, l, j+1)
    partition(L, j, h)

QuickSort(L,l,h)
print(L)

我的最终结果:[10, 20, 30, 35,50, 40, 60, 70, 90](把60放在正确的位置后,程序结束)

我曾尝试对 QuickSort 功能进行如下更改(参考其他答案后),但结果更加混乱......

def QuickSort( L, l, h):
    print(l, h)
    j = partition(L, l, h)
    partition(L, l, j)
    partition(L, j+1, h)

【问题讨论】:

  • 我还没有完全调查你的代码,但是你对QuickSort 的定义是错误的。你的最后两个函数调用应该是对QuickSort的递归调用,否则你只会分区3次然后退出。您确实需要在某处添加基本案例以停止递归。
  • 好吧...我明白了。是否可以对相同的代码进行更改以实现这一目标?

标签: python-3.x sorting quicksort


【解决方案1】:

您对QuickSort 的实现不正确。它不是递归的,它只是调用partition 三次,它不会对包含多个元素的列表进行完全排序。后面的两个调用应该是对QuickSort 的递归调用。

当然,当您使代码递归时,您还需要添加一个基本情况,以便递归结束。幸运的是,通过查看lh,很容易看出何时不需要进一步排序。列表中少于两个元素的部分不再需要排序。

我会这样做:

def QuickSort(L, l, h):
    if h - l < 2:            # add a base case
        return
    j = partition(L, l, h)
    QuickSort(L, l, j)       # recurse
    QuickSort(L, j+1, h)     # here too

作为旁注,通常不鼓励使用l(小写L)作为变量名,因为在某些字体中很难区分它和1(一位数)。我也会避免使用仅在大小写上不同的变量(如lL 所做的那样)。更好的名称更具描述性。虽然ij 有时可以用于索引,但对于几乎任何稍微复杂一点的东西,我更喜欢带有更多字母的名称。在这种情况下,lowhigh 可能是参数的更好名称。

【讨论】:

  • 只是一个更正,因为我的代码 QuickSort(L, l, j)QuickSort(L, j, h) 将被调用
  • @ThePerson:您不希望j(分区中枢轴的索引)包含在将由递归调用排序的列表部分中。如果你把它留在里面,你会冒无限递归的风险,如果某些子列表一直被分区到一侧,包括枢轴元素。
猜你喜欢
  • 2015-06-12
  • 2017-03-05
  • 1970-01-01
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 2016-08-14
  • 1970-01-01
相关资源
最近更新 更多