как сделать метод сортировки в smalltalk

Я пытаюсь создать новый метод сортировки в smalltalk. Кто-нибудь знает, как изменить этот java-код сортировки на писк?

public static void SelectionSort ( int [ ] num )
{
     int i, j, first, temp;  
     for ( i = num.length - 1; i > 0; i - - )  
     {
          first = 0;   //initialize to subscript of first element
          for(j = 1; j <= i; j ++)   //locate smallest element between positions 1 and i.
          {
               if( num[j] < num[first] )         
                 first = j;
          }
          temp = num[first];   //swap smallest found with element in position i.
          num[first] = num[ i ];
          num[i] = temp; 
      }           
}

person programmingGirl    schedule 30.04.2015    source источник


Ответы (2)


Вот построчный перевод. Номера строк не являются частью кода.

 1. selectionSort: num
 2.    | first temp |
 3.    num size to: 1 by: -1 do: [:i |
 4.        first := 1. "initialize to subscript of first element"
 5.        1 to: i do: [:j |
 6.            "locate smallest element between positions 1 and i"
 7.            (num at: j) < (num at: first) ifTrue: [first := j]].
 8.        temp := num at: first. "swap smallest with element in position i"
 9.        num at: first put: (num at: i).
10.        num at: i put: temp]

Примечания:

  1. Нет объявления типа аргумента. Нет типа ответа.
  2. Временные блоки i и j объявлены внутри блоков (строки 3 и 5). В Smalltalk индексированные коллекции основаны на 1.
  3. num.length() -> num size. Уменьшение цикла for преобразуется в сообщение to:by:do:.
  4. Назначение = становится :=, а 0 становится 1 (см. примечание 2 к строке выше).
  5. Увеличение цикла for преобразуется в сообщение to:do:.
  6. Комментарии заключены в двойные кавычки.
  7. [j] переводится в сообщение at: j. if преобразуется в сообщение ifTrue:.
  8. temp можно было бы объявить в первом блоке: do: [:i | | temp |....
  9. num[j] = temp также становится отправкой сообщения at:put:.
  10. То же 9. Обратите также внимание, что вы могли бы использовать каскадный синтаксис для строк 9 и 10:

    num
        at: first put: (num at: i);
        at: i put: temp
    
  11. Нет необходимости отвечать num, потому что метод изменил его. См., однако, интересную дискуссию, возникшую в ответе Амоса: Почему я не должен хранить в буквальных массивах в Smalltalk?.

person Leandro Caniglia    schedule 30.04.2015
comment
Благодарю вас! это было очень ясно и полезно! я немного изменил способ, но это объяснило код шаг за шагом. - person programmingGirl; 01.05.2015

Короткий ответ:

Вам не нужно.

Чтобы отсортировать массив, просто отправьте ему сообщение #asSortedCollection. Например, проверьте это в рабочей области:

#(7 2 8 5) asSortedCollection

Длинный ответ:

Поскольку я предполагаю, что вы хотите увидеть, как вы будете реализовывать эквивалент вашего Java-кода в Smalltalk, если вам действительно придется, вот относительно "буквальный перевод", который вы можете протестировать в рабочее пространство (проверено в Pharo, должно работать и в Squeak):

| someNumbers |
someNumbers := #(7 2 8 5) copy. "See comments below for an explanation."
someNumbers size to: 1 by: -1 do: [:eachOuterIndex |
    | indexOfSmallest swapValue |
    indexOfSmallest := 1.
    1 to: eachOuterIndex do: [:eachInnerIndex |
        (someNumbers at: eachInnerIndex) < (someNumbers at: indexOfSmallest)
            ifTrue: [ indexOfSmallest := eachInnerIndex ]
        ].
    swapValue := someNumbers at: indexOfSmallest.
    someNumbers at: indexOfSmallest put: (someNumbers at: eachOuterIndex).
    someNumbers at: eachOuterIndex put: swapValue.
    ].
^someNumbers

Очевидно, есть несколько изменений по сравнению с вашей версией, например, использование явного именования, которое является одним из отличительных признаков Smalltalk (в частности, indexOfSmallest должно быть понятнее, чем first, что вводит в заблуждение, поскольку это не обязательно первый индекс), и уменьшение область переменных, которые вы назвали first и temp). См. Ответ @Leandro для версии, в которой используются ваши собственные имена переменных, если у вас возникли проблемы с «переводом».

Если бы код жил в методе, я бы, вероятно, поместил его в иерархию SequenceableCollection (или, может быть, вы хотели бы добавить туда свой подкласс, если хотите переопределить другое поведение), и его начало могло бы выглядеть что-то вроде этого:

copySortedDescending
    "Answer a copy of the receiver, sorted in descending order."

    | copy |
    copy := self copy.
    copy size to: 1 by: -1 do: [:eachOuterIndex |
        "... and so on..."
        ].
    ^copy

Опять же, обратите внимание, что я намеренно меняю имя, потому что я не думаю, что selectionSort — это описательное имя того, что делает метод, и я бы не стал использовать коллекцию в качестве аргумента для метода, живущего где-то еще — знание как сделать сортировку принадлежит самой коллекции.

Я уверен, что вы могли бы очень легко придумать лучший ответ. Например, вы можете попробовать отправить экземпляру SequenceableCollection сообщение sort: и передать блок сортировки в качестве аргумента, в котором вы можете указать, как вы хотите, чтобы ваши элементы были отсортированы.

person Amos M. Carpenter    schedule 30.04.2015
comment
Ваш код в основном правильный, но вы не должны хранить его в буквальном массиве (#(...)). Вероятно, изменить первую строку на someNumbers := #(7 2 8 5) copy. - person Tobias; 30.04.2015
comment
@Tobias: Как я уже сказал, это должен быть буквальный перевод кода OP. А в Pharo он работает как есть... почему бы не изменить в нем значения? Я не перебираю массив, я перебираю индексы. - person Amos M. Carpenter; 30.04.2015
comment
Да это верно. Но предположим, что вы пишете этот код в методе. вы ожидаете, что каждый раз, когда вы его вызываете, первая строка будет одной и той же, но это не так после первого вызова. Это немного сложно, поэтому я сделал запись в вики сообщества: 29964346" title="почему я не должен хранить в литеральных массивах в smalltalk"> stackoverflow.com/questions/29964345/ - person Tobias; 30.04.2015
comment
@Tobias: Я ценю усилия, которые вы приложили, чтобы изложить свою точку зрения, что является довольно сложным случаем - я проголосовал за ваш вопрос и ваш ответ. Если бы этот код должен был жить в методе, а не просто быть примером рабочей области, очевидно, что литеральный массив не использовался бы в первую очередь - массив был бы аргументом, и метод был бы наиболее скорее всего ответит отсортированная копия получателя. Рад обновить ответ, включив в него copy, спасибо, что указали на это. - person Amos M. Carpenter; 30.04.2015