关于python:将列表的一部分排序到位

Sort a part of a list in place

假设我们有一个列表:

1
a = [4, 8, 1, 7, 3, 0, 5, 2, 6, 9]

现在,a.sort()将对列表进行排序。 如果我们只想对列表的一部分进行排序,该怎么办? 在C ++中,我们可以编写:

1
2
3
int array = { 4, 8, 1, 7, 3, 0, 5, 2, 6, 9 };
int * ptr = array;
std::sort( ptr + 1, ptr + 4 );

Python中有类似的方法吗?


我会这样写:

1
a[i:j] = sorted(a[i:j])

它也不是就地排序,但是对于相对较小的段来说足够快。

请注意,Python仅复制对象引用,因此与真正的就地排序相比,速度损失不会那么大。


如果anumpy数组,则要就地排序[i, j)范围,请键入:

1
a[i:j].sort()

例:

1
2
3
4
5
>>> import numpy as np
>>> a = np.array([4, 8, 1, 7, 3, 0, 5, 2, 6, 9])
>>> a[1:4].sort()
>>> a
array([4, 1, 7, 8, 3, 0, 5, 2, 6, 9])


要在两个索引之间进行排序,我建议使用quicksort。与array[start:end] = sorted(arr[start:end])相比,快速排序的优势在于,快速排序不需要任何额外的内存,而分配给分片则需要O(n)额外的内存。

我不相信标准库中有实现,但是编写自己很容易。这是我从https://www.geeksforgeeks.org/quicksort-using-random-pivoting/复制并粘贴的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import random

def quicksort(arr, start , stop):
    if(start < stop):
        pivotindex = partitionrand(arr, start, stop)
        quicksort(arr , start , pivotindex - 1)
        quicksort(arr, pivotindex + 1, stop)


def partitionrand(arr , start, stop):

    randpivot = random.randrange(start, stop)

    arr[start], arr[randpivot] = arr[randpivot], arr[start]
    return partition(arr, start, stop)


def partition(arr,start,stop):
    pivot = start # pivot
    i = start + 1 # a variable to memorize where the  
                  # partition in the array starts from.
    for j in range(start + 1, stop + 1):
        if arr[j] <= arr[pivot]:
            arr[i] , arr[j] = arr[j] , arr[i]
            i = i + 1
    arr[pivot] , arr[i - 1] = arr[i - 1] , arr[pivot]
    pivot = i - 1
    return (pivot)

为了在示例(包括范围)中的索引2和6之间进行排序,我将执行以下操作:

1
2
3
array = [4, 8, 1, 7, 3, 0, 5, 2, 6, 9]
quicksort(array, 2, 6)
print(array)