Выбор Сортировки В Python

Это может показаться простым вопросом, но когда я попытался реализовать сортировку выбора в Python, я не получаю отсортированного списка. Что-то не так с моей реализации? Подмножество может быть проблемой.

source = [4,2,1,10,5,3,100]
for i in range(len(source)):
  mini = min(source[i:]) #find minimum element
  min_index = source[i:].index(mini)-1 #find index of minimum element
  source[i:][min_index]= source[i:][0] #replace element at min_index with first element
  source[i:][0] = mini                  #replace first element with min element
print source

12 ответов


Я думаю, что было несколько проблем.

во-первых, когда ваш источник do[i:], я считаю, что возвращает новый массив запрошенных подэлементов, а не часть исходного массива, поэтому, если вы измените его, вы не измените оригинал. Во-вторых, вы вычитали 1 из индекса, когда не должны были.

source = [4,2,1,10,5,3,100]
for i in range(len(source)):
    mini = min(source[i:]) #find minimum element
    min_index = source[i:].index(mini) #find index of minimum element
    source[i + min_index] = source[i] #replace element at min_index with first element
    source[i] = mini                  #replace first element with min element
print source

это дает:

[1, 2, 3, 4, 5, 10, 100]

вот как я бы переписал ваш код. Конечно, в Python, я бы просто использовать list.sort() для сортировки списка, но вот сортировка выбора в Python.

мы делаем выражение генератора, которое возвращает кортежи (value, i) для значения и его индекса из списка. Тогда когда min() оценивает, чтобы найти минимум, он находит наименьшее значение кортежа; так как значение приходит первым в кортеж перед индексом, значение будет важной частью, и min() найдет наименьшее значение. (Если есть галстук, min() будет использовать вторую часть кортежа, индекс, в качестве тай-брейкера. Но для сорта нам все равно, как порваны связи.)

теперь, вместо того, чтобы искать через Под-список, чтобы найти минимальное значение, а затем искать через него снова, чтобы выяснить индекс, мы ищем через него один раз и получить как минимальное значение и индекс.

но мы на самом деле не заботимся о минимальном значении; мы заботимся об индексе. Так после min() готово, мы просто выбрасываем фактическое значение, но сохранить индекс. Отрегулируйте индекс, чтобы быть правильным во всем списке (не в срезе списка), а затем мы можем поменять местами.

мы используем стандартную идиому Python для замены двух значений. Python построит объект кортежа в качестве промежуточного, а затем распакует этот кортеж в левую сторону.

lst = [4,2,1,10,5,3,100]

for i_sortpos in range(len(lst)):
    # Make a generator expression to return (value, i) pairs.
    genexp = ((n, i) for i, n in enumerate(lst[i_sortpos:]))
    # Use genexp with min() to find lowest and its index.
    # (Use '_' for variable name for the actual value; we don't use it.)
    _, i_min = min(genexp)
    # Adjust index to be correct in full list.
    i_min += i_sortpos
    # Swap the number at i_sortpos with the lowest found.
    lst[i_sortpos], lst[i_min] = lst[i_min], lst[i_sortpos]

print(lst)

EDIT: и вот уточнение вышеизложенного. Срез из списка фактически выделяет новый список; нашему коду здесь не нужен новый список, ему просто нужен удобный способ изучить подсписок. The itertools модуль предлагает функцию,islice(), который возвращает итератор, который выполняет итерацию по срезу списка. Это позволяет избежать многократного создания и уничтожения списков при рассмотрении каждого подсписка.

я считаю, что это самый эффективный способ сделать выбор сортировки в Python. (Вы можете избавиться от части, где мы связываем выражение генератора с именем genexp и сэкономить несколько микросекунд... просто позвоните в min() один длинный-вкладыш. Но это не стоит потери читаемости.)

import itertools as it

lst = [4,2,1,10,5,3,100]

for i_sortpos in range(len(lst)):
    # Make a generator expression to return (value, i) pairs.
    # Use it.islice() for to look at sublist.
    genexp = ((n, i) for i, n in enumerate(it.islice(lst, i_sortpos, len(lst))))
    # Use genexp with min() to find lowest and its index.
    # (Use '_' for variable name for the actual value; we don't use it.)
    _, i_min = min(genexp)
    # Adjust index to be correct in full list.
    i_min += i_sortpos
    # Swap the number at i_sortpos with the lowest found.
    lst[i_sortpos], lst[i_min] = lst[i_min], lst[i_sortpos]

print(lst)

или вы можете попробовать так:

arr = [5,4,3,1,6,8,10,9] # array not sorted

for i in range(len(arr)):
    for j in range(i, len(arr)):
        if(arr[i] > arr[j]):
            arr[i], arr[j] = arr[j], arr[i]

print arr

def selectionSort(List_):
    for i in range(len(List_)):`
        #track the current smallest value
        smallIndex = i
            #loop from the current smallest value
            for j in range(i+1,len(List_))
                if List_[j] < List_[smallIndex]:
                    #if new value is less that our smallest value,change 
                    #smallest value to this
                    smallIndex = j
            if smallIndex != i:
                #swap the values
                List_[smallIndex],List_[i] = List_[i],List_[smallIndex]
    #return sorted list
    return List_

def ss(l):    
    for i in range(0,len(l)):
        d=l.index(min(l[i:]))        
        c=l[i]
        l[i]=min(l[i:])
        l[d]=c
        print(l)  #it prints each step of selection sort
y=[10,9,1,5,0,6]
ss(y)

def selSort(L):
    """
    Find the smallest element in the list and put it (swap it) in the first location, 
    Find the second element and put it (swap it) in the second locaiton, and so on. 

    """
    for i in range(len(L) - 1):
        minIndx = i
        minVal= L[i]
        j = i + 1
        while j < len(L):
            if minVal > L[j]:
                minIndx = j
                minVal= L[j]
            j += 1
        temp = L[i]
        L[i] = L[minIndx]
        L[minIndx] = temp 
    return L

звоните:

print( selSort([120,11,0,1,3,2,3,4,5,6,7,8,9,10]) )

выход

[0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 120]

s = [1,8,4,9,3,6,2]
for i in range(len(s)):
    maxi = max(s[0:len(s)-i])     #find max element
    tempi = s.index(maxi)         # find index of max element
    temp = s[len(s)-1-i]          #assign last element as temp
    s[len(s)-1-i] = maxi          #put max element in last position
    s[tempi] = temp               # put the element initially at last in its new 

print s    

вот что я думаю, это хороший способ отсортировать список чисел, и я надеюсь, что это поможет:

list=[5,4,3,1,6,8,10,9]
listsorted=[]
for i in range(len(list)):
    x=min(list)
    list.remove(x)
    listsorted.append(x)
print listsorted 

и результат будет [1, 3, 4, 5, 6, 8, 9, 10]


Я думаю, что" принятый " ответ здесь бесполезен. Если мы посмотрим, например,

mini = min(source[i:]) #find minimum element
min_index = source[i:].index(mini) #find index of minimum element

это не только неэффективно с точки зрения создания ненужных срезов списка, но и ненужного поиска. Это достаточно лаконично, но я не думаю, что это лучшее решение.


def Selection_Sort(Sarray):
    length = len(Sarray)
    i = 0
    j = 0
    for i in range(length):
        j = i+1
        for j in range(length):
            if Sarray[i] < Sarray[j]
                t = Sarray[i]
                Sarray[i] = Sarray[j]
                Sarray[j] = t
        j = j+1
        i = i+1

    return Sarray

код выбора сортировки из онлайн-курса MIT .

def selSort(L):
    for i in range(len(L) - 1):
        minIndx = i
        minVal = L[i]
        j = i+1
        while j < len(L):
            if minVal > L[j]:
                minIndx = j
                minVal = L[j]
            j += 1
        if minIndx != i:
            temp = L[i]
            L[i] = L[minIndx]
            L[minIndx] = temp

def selectSort(L):
  for i in range(len(L)):
    print L
    minIndex = i
    minValue = L[i]
    j = i + 1
    while j < len(L):
        if minValue > L[j]:
            minIndex = j
            minValue = L[j]  
        j +=1
    temp = L[i]
    L[i] = L[minIndex]
    L[minIndex] = temp