Python

Key Functions

Starting with Python 2.4, both list.sort() and sorted() added a key parameter to specify a function to be called on each list element prior to making comparisons.

For example, here’s a case-insensitive string comparison:

>>> sorted("This is a test string from Andrew".split(), key=str.lower)

The value of the key parameter should be a function that takes a single argument and returns a key to use for sorting purposes. This technique is fast because the key function is called exactly once for each input record.

A common pattern is to sort complex objects using some of the object’s indices as a key. For example:

>>> student_tuples = 
>>> sorted(student_tuples, key=lambda student: student)   # sort by age

The same technique works for objects with named attributes. For example:

>>> class Student:
        def __init__(self, name, grade, age):
                self.name = name
                self.grade = grade
                self.age = age
        def __repr__(self):
                return repr((self.name, self.grade, self.age))
        def weighted_grade(self):
                return 'CBA'.index(self.grade) / float(self.age)

>>> student_objects = 
>>> sorted(student_objects, key=lambda student: student.age)   # sort by age

Плавная сортировка :: Smoothsort

  • I. Создаём из массива кучу леонардовых куч, каждая из которых является сортирующим деревом.

    • I.1. Перебираем элементы массива слева-направо.
    • II.1. Проверяем, можно ли с помощью текущего элемента объединить две крайние слева кучи в уже имеющейся куче леонардовых куч:

      • II.1.а. Если да, то объединяем две крайние слева кучи в одну, текущий элемент становится корнем этой кучи, делаем просейку для объединённой кучи.
      • II.1.б. Если нет, то добавляем текущий элемент в качестве новой кучи (состоящей пока из одного узла) в имеющуюся кучу леонардовых куч.
  • II. Извлекаем из куч текущие максимальные элементы, которые перемещаем в конец неотсортированной части массива:

    • II.1. Ищем максимумы в леонардовых кучах. Так как на предыдущем этапе для куч постоянно делалась просейка, максимумы находятся в корнях этих куч.
    • II.2. Найденный максимум (который является корнем одной из куч) меняем местами с последним элементом массива (который является корнем самой последней кучи).
    • II.3. После этого обмена куча, в которой был найден максимум перестала быть сортирующим деревом. Поэтому делаем для неё просейку.
    • II.4. В последней куче удаляем корень (в которой находится текущий максимум), в результате чего эта куча распадается на две кучи поменьше.
    • II.5. После перемещения максимального элемента в конец, отсортированная часть массива увеличилась, а неотсортированная часть уменьшилась. Повторяем пункты II.1-II.4 для оставшейся неотсортированной части массива.

Sorting Ascending and Descending

The first time you click the button, the sorting direction is ascending (A to Z).

Click again, and the sorting direction will be descending (Z to A):

Sort

  • Oslo
  • Stockholm
  • Helsinki
  • Berlin
  • Rome
  • Madrid

Example

<ul id=»id01″>  <li>Oslo</li>  <li>Stockholm</li> 
<li>Helsinki</li>  <li>Berlin</li>  <li>Rome</li> 
<li>Madrid</li></ul><script>function sortListDir() { 
var list, i, switching, b, shouldSwitch, dir, switchcount = 0;  list
= document.getElementById(«id01»);  switching = true;  // Set
the sorting direction to ascending:  dir = «asc»;   // Make a
loop that will continue until no switching has been done:  while
(switching) {    // Start by saying: no switching is done:   
switching = false;    b = list.getElementsByTagName(«LI»);   
// Loop through all list-items:    for (i = 0; i < (b.length
— 1); i++) {      // Start by saying there should
be no switching:      shouldSwitch = false;     
/* Check if the next item should switch place with the current item,     
based on the sorting direction (asc or desc): */     
if (dir == «asc») {        if (b.innerHTML.toLowerCase()
> b.innerHTML.toLowerCase()) {         
/* If next item is alphabetically lower than current item,         
mark as a switch and break the loop: */         
shouldSwitch = true;         
break;        }     
} else if (dir == «desc») {        if
(b.innerHTML.toLowerCase() < b.innerHTML.toLowerCase()) {         
/* If next item is alphabetically higher than current item,         
mark as a switch and break the loop: */         
shouldSwitch= true;         
break;        }     
}    }    if (shouldSwitch) {     
/* If a switch has been marked, make the switch     
and mark that a switch has been done: */     
b.parentNode.insertBefore(b, b);     
switching = true;      // Each time a switch is
done, increase switchcount by 1:      switchcount
++;    } else {      /* If no
switching has been done AND the direction is «asc»,     
set the direction to «desc» and run the while loop again. */     
if (switchcount == 0 && dir == «asc») {       
dir = «desc»;        switching = true;     
}    }  }}</script>

Сортировка массива в Python

Метод Пузырька

Сортировку массива в python будем выполнять :

1
2
3
4
5
6
7
8
9
10
11
12
13
import random
from random import randint 
 
mas = randint(1,10) for i in range(n)
for i in range(n):
                print(masi,sep="")
print("   ")
for i in range(n-1):
                for j in range(n-2, i-1 ,-1):
                                if masj+1 < masj:
                                                masj, masj+1 = masj+1, masj
for i in range(n):
                print(masi,sep="")

Задание Python 7_4:
Необходимо написать программу, в которой сортировка выполняется «методом камня» – самый «тяжёлый» элемент опускается в конец массива.

Быстрая сортировка массива

Данную сортировку еще называют или сортировка Хоара (по имени разработчика — Ч.Э. Хоар).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import random
from random import randint
# процедура
def qSort ( A, nStart, nEnd ):
                if nStart >= nEnd: return
                L = nStart; R = nEnd
                X = A(L+R)//2
                while L <= R:
                                while AL < X: L += 1 # разделение
                                while AR > X: R -= 1
                                if L <= R:
                                                AL, AR = AR, AL
                                                L += 1; R -= 1
                qSort ( A, nStart, R ) # рекурсивные вызовы
                qSort ( A, L, nEnd )
N=10
A = randint(1,10) for i in range(N)
print(A)
# вызов процедуры
qSort ( A, , N-1 )
print('отсортированный', A)

Задание Python 7_5:
Необходимо написать программу, которая сортирует массив (быстрой сортировкой) по возрастанию первой цифры числа.

Встроенные функции

  1. mas.reverse() — стандартный метод для перестановки элементов массива в обратном порядке;
  2. mas2 = sorted (mas1) — встроенная функция для сортировки массивов (списков);

Задание Python 7_6:
Напишите программу, которая, не изменяя заданный массив, выводит номера его элементов в возрастающем порядке. Использовать вспомогательный массив номеров.

Задание Python 7_7:
Напишите программу, которая сортирует массив и находит количество различных чисел в нём. Не использовать встроенные функции.

Задание Python 7_8:
Дан массив. Назовем серией группу подряд идущих одинаковых элементов, а длиной серии — количество этих элементов. Сформировать два новых массива, в один из них записывать длины всех серий, а во второй — значения элементов, образующих эти серии.

Задание Python 7_9:
Напишите вариант метода пузырька, который заканчивает работу, если на очередном шаге внешнего цикла не было перестановок. Не использовать встроенные функции.

Задание Python 7_10:
Напишите программу, которая сортирует массив, а затем находит максимальное из чисел, встречающихся в массиве несколько раз. Не использовать встроенные функции.

Входные данные не меняются

Пусть есть два списка и .

Начнем с самого простого алгоритма: обозначим метки за и и будем брать меньший из , и увеличивать его метку на единицу, пока одна из меток не выйдет за границу списка.

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

Перейдем к коду:

Заметим, что в данном коде используется только перемещение вперед по списку. Поэтому будет достаточно работать с итераторами. Перепишем алгоритм с помощью итераторов.

Еще изменим обработку концов списков, так как теперь мы не умеем копировать сразу до конца. Будем обрабатывать элементы до того, когда оба итератора дойдут до конца, при этом, если один уже оказался в конце, будем просто брать из второго.

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

Встроенные реализации

Рассмотрим еще несколько способов слияния через встроенные в python функции.

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

    Тогда нам нужно просто импортировать и использовать:

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

    Воспользуемся для слияния элементов и :

  • И, наконец, просто сортировка. Объединяем и сортируем заново.

The Old Way Using Decorate-Sort-Undecorate

This idiom is called Decorate-Sort-Undecorate after its three steps:

  • First, the initial list is decorated with new values that control the sort order.
  • Second, the decorated list is sorted.
  • Finally, the decorations are removed, creating a list that contains only the initial values in the new order.

For example, to sort the student data by grade using the DSU approach:

>>> decorated = 
>>> decorated.sort()
>>>                # undecorate

This idiom works because tuples are compared lexicographically; the first items are compared; if they are the same then the second items are compared, and so on.

It is not strictly necessary in all cases to include the index i in the decorated list. Including it gives two benefits:

  • The sort is stable — if two items have the same key, their order will be preserved in the sorted list.
  • The original items do not have to be comparable because the ordering of the decorated tuples will be determined by at most the first two items. So for example the original list could contain complex numbers which cannot be sorted directly.

Another name for this idiom is Schwartzian transform, after Randal L. Schwartz, who popularized it among Perl programmers.

For large lists and lists where the comparison information is expensive to calculate, and Python versions before 2.4, DSU is likely to be the fastest way to sort the list. For 2.4 and later, key functions provide the same functionality.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector