Понимание python bubble sort с примерами

Содержание:

Сортировка пузырьком

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

Пузырьковая (обменная) использует двумерный или одномерный массив и механизм обмена. Большинство языков программирования имеют встроенную функцию для перестановки элементов. Даже если функция обмена не существует, требуется всего пара дополнительных строк кода. Вместо перебора массива, пузырьковая работает по схеме сравнения соседних пар объектов. Шаги:

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

Сортировка пузырьком на Pascal (Паскаль):

Сортировка массива методом пузырька на Python (Питон):

На Java:

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

Какой способ обработки данных выбрать, специалист решает сам, в зависимости от времени и объема информации.

Пример работы алгоритма

Возьмём массив с числами «5 1 4 2 8» и отсортируем значения по возрастанию, используя сортировку пузырьком. Выделены те элементы, которые сравниваются на данном этапе.

Наглядная демонстрация алгоритма.

Первый проход:

(5 1 4 2 8) (1 5 4 2 8), Здесь алгоритм сравнивает два первых элемента и меняет их местами.
(1 5 4 2 8) (1 4 5 2 8), Меняет местами, так как 5>4{\displaystyle 5>4}
(1 4 5 2 8) (1 4 2 5 8), Меняет местами, так как 5>2{\displaystyle 5>2}
(1 4 2 5 8) (1 4 2 5 8), Теперь, ввиду того, что элементы стоят на своих местах (8>5{\displaystyle 8>5}), алгоритм не меняет их местами.

Второй проход:

(1 4 2 5 8) (1 4 2 5 8)
(1 4 2 5 8) (1 2 4 5 8), Меняет местами, так как 4>2{\displaystyle 4>2}
(1 2 4 5 8) (1 2 4 5 8)

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

Третий проход:

(1 2 4 5 8) (1 2 4 5 8)
(1 2 4 5 8) (1 2 4 5 8)

Теперь массив отсортирован и алгоритм может быть завершён.

Не спеша, эффективно и правильно – путь разработки. Часть 2. Теория

Черновой вариант книги Никиты Зайцева, a.k.a.WildHare. Разработкой на платформе 1С автор занимается с 1996-го года, специализация — большие и по-хорошему страшные системы. Квалификация “Эксперт”, несколько успешных проектов класса “сверхтяжелая”. Успешные проекты ЦКТП. Четыре года работал в самой “1С”, из них два с половиной архитектором и ведущим разработчиком облачной Технологии 1cFresh. Ну — и так далее. Не хвастовства ради, а понимания для. Текст написан не фантазером-теоретиком, а экспертом, у которого за плечами почти двадцать три года инженерной практики на больших проектах.

Пример:

Пусть исходный массив будет .

Первая итерация:
сравните элементы в индексах 1 и 2: 5, 4. Они не отсортированы. Поменяйте их местами. Array = .
Сравните элементы в индексе 2 и 3: 5, 9. Они отсортированы. Не меняйте местами. Array = .
Сравните элементы в индексе 3 и 4: 9, 3. Они не отсортированы. Поменяйте их местами. Array = .
Сравните элементы в индексе 4 и 5: 9, 7. Они не отсортированы. Поменяйте их местами. Array = .
Сравните элементы в индексе 5 и 6: 9, 6. Они не отсортированы. Поменяйте их местами. Array =
Массив после первой итерации равен .

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

Первая итерация:

Вторая итерация:

Третья итерация:

Исходный код: пузырьковая сортировка

def bubble_sort(arr, n):
for i in range(0, n):
for j in range(0, n-1):
# Если пара не находится в отсортированном порядке
if arr > arr:
# Поменяйте местами пары, чтобы сделать их в отсортированном порядке
arr, arr = arr, arr
return arr

if __name__ == "__main__":
arr = 
n = len(arr)
arr = bubble_sort(arr, n)
print (arr)

Пояснение: Алгоритм состоит из двух циклов. Первый цикл повторяется по массиву n раз, а второй цикл n-1 раз. На каждой итерации первого цикла второй цикл сравнивает все пары соседних элементов. Если они не отсортированы, соседние элементы меняются местами, чтобы упорядочить их. Максимальное количество сравнений, необходимых для присвоения элементу его правой позиции в отсортированном порядке, равно n-1, потому что есть n-1 других элементов. Так как имеется n элементов, и каждый элемент требует максимум n-1 сравнений; массив сортируется за время O (n ^ 2). Следовательно, временная сложность наихудшего случая равна O (n ^ 2). Лучшая временная сложность в этой версии пузырьковой сортировки также составляет O (n ^ 2), потому что алгоритм не знает, что он полностью отсортирован. Следовательно, даже если он отсортирован.

Использовать ли шейкер сортировку

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

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

Конечно шейкер сортировка лучше пузырьковой сортировки, но по сравнению с другими алгоритмами она отстает и даже намного (!).

  • Плюс один, как и у многих простеньких алгоритмов — простая реализация.
  • Минус один — медленная работа алгоритма.

Если вы знаете только пузырьковую и шейкер сортировку, то лучше используйте последнюю сортировку. Так вы хоть не намного, но увеличите скорость вашей программы.

Java, с инициализацией и перемешиванием массива и с измерением времени сортировки массива нанотаймером (работает только если нет совпадающих элементов массива)

import java.util.Random;
 
public class QuickSort {
    public static void main(String[] args) {
       int N=10;
       int A[];
       A = new int;
       // заполнение массива
       for (int i=0;i<=N;i=i+1) {
          A=N-i;
          System.out.print(A+" ");
       }
       System.out.println("\nBefore qSort\n");
       // перемешивание массива
       Random r = new Random(); //инициализация от таймера
       int yd,xs;
       for (int i=0;i<=N;i=i+1) {
          yd=A;
          xs=r.nextInt(N+1);
          A=A;
          A=yd;
       }
       for (int i=0;i<=N;i=i+1)
          System.out.print(A+" ");
       System.out.println("\nAfter randomization\n");
       long start, end;
       int low=0;
       int high=N;
 
       start=System.nanoTime();   // получить начальное время
       qSort(A,low,high);
       end=System.nanoTime();    // получить конечное время
 
       for (int i=0;i<=N;i++)
          System.out.print(A+" ");
       System.out.println("\nAfter qSort");
       System.out.println("\nTime of running: "+(end-start)+"nanosec");
    }
   //описание функции qSort
   public static void qSort(int[] A, int low, int high) {
      int i = low;
      int j = high;
      int x = A[(low+high)/2];
      do {
         while(A < x) ++i;
         while(A > x) --j;
         if(i <= j){
            int temp = A;
            A = A;
            A = temp;
            i ++ ; j --;
         }
      } while(i <= j);
      //рекурсивные вызовы функции qSort
      if(low < j) qSort(A, low, j);
      if(i < high) qSort(A, i, high);
  }
}

Используйте [ редактировать ]

Пузырьковая сортировка — алгоритм сортировки, который непрерывно просматривает список, меняя местами элементы, пока они не появятся в правильном порядке. Список был построен в декартовой системе координат, где каждая точка ( x , y ) указывает, что значение y хранится в индексе x . Затем список будет отсортирован пузырьковой сортировкой по значению каждого пикселя

Обратите внимание, что сначала сортируется самый большой конец, а меньшим элементам требуется больше времени, чтобы переместиться в правильное положение.

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

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

Жаргон Файл , который лихо звонков bogosort «архетипический извращенно ужасный алгоритм», также вызывает пузырьковую сортировку «общий плохой алгоритм». Дональд Кнут в книге «Искусство компьютерного программирования» пришел к выводу, что «пузырьковая сортировка, похоже, не имеет ничего, что могло бы ее рекомендовать, кроме броского названия и того факта, что она приводит к некоторым интересным теоретическим проблемам», некоторые из которых он затем обсуждает. .

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

Пузырьковая сортировка также плохо взаимодействует с современным аппаратным обеспечением ЦП. Он производит как минимум вдвое больше записей, чем сортировка вставкой, вдвое больше промахов в кеш и асимптотически больше ошибочных прогнозов переходов . [ необходима цитата ] Эксперименты по сортировке строк Astrachan в Java показывают, что пузырьковая сортировка примерно в пять раз быстрее сортировки вставкой и на 70% быстрее сортировки по выбору .

В компьютерной графике пузырьковая сортировка популярна благодаря своей способности обнаруживать очень маленькие ошибки (например, перестановку всего двух элементов) в почти отсортированных массивах и исправлять их с линейной сложностью (2 n ). Например, он используется в алгоритме заполнения многоугольника, где ограничивающие линии сортируются по их координате x в определенной строке сканирования (линия, параллельная оси x ), а с увеличением y их порядок изменяется (два элемента меняются местами) только при пересечения двух линий. Пузырьковая сортировка — это стабильный алгоритм сортировки, как и сортировка вставкой.

Таблица 2: Сортировка пузырьком в многопоточном режиме

1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
2 1 3 4 5 6 7 8 9 10 11 12 13 14
2 3 1 4 5 6 7 8 9 10 11 12 13 14
3 2 4 1 5 6 7 8 9 10 11 12 13 14
3 4 2 5 1 6 7 8 9 10 11 12 13 14
4 3 5 2 6 1 7 8 9 10 11 12 13 14
4 5 3 6 2 7 1 8 9 10 11 12 13 14
5 4 6 3 7 2 8 1 9 10 11 12 13 14
5 6 4 7 3 8 2 9 1 10 11 12 13 14
6 5 7 4 8 3 9 2 10 1 11 12 13 14
6 7 5 8 4 9 3 10 2 11 1 12 13 14
7 6 8 5 9 4 10 3 11 2 12 1 13 14
7 8 6 9 5 10 4 11 3 12 2 13 1 14
8 7 9 6 10 5 11 4 12 3 13 2 14 1
8 9 7 10 6 11 5 12 4 13 3 14 2 1
9 8 10 7 11 6 12 5 13 4 14 3 2 1
9 10 8 11 7 12 6 13 5 14 4 3 2 1
10 9 11 8 12 7 13 6 14 5 4 3 2 1
10 11 9 12 8 13 7 14 6 5 4 3 2 1
11 10 12 9 13 8 14 7 6 5 4 3 2 1
11 12 10 13 9 14 8 7 6 5 4 3 2 1
12 11 13 10 14 9 8 7 6 5 4 3 2 1
12 13 11 14 10 9 8 7 6 5 4 3 2 1
13 12 14 11 10 9 8 7 6 5 4 3 2 1
13 14 12 11 10 9 8 7 6 5 4 3 2 1
14 13 12 11 10 9 8 7 6 5 4 3 2 1
14 13 12 11 10 9 8 7 6 5 4 3 2 1

Сортировка массива методом пузырька- решение на C++

Сортировка массива методом пузырька- решение на C++

Алгоритм пузырьковой сортировки — это довольно простой в реализации алгоритм для сортировки массивов. Можно встретить и другие названия: пузырьковая сортировка, Bubble sort или сортировка простыми обменами — но все они будут обозночать один и тот же алгоритм. Назван так, потому что большее или меньшее значение «всплывает» (сдвигается) к краю массива после каждой итерации, это будет видно в примере.

Исходный код на языке C++

/*
* Ввести целочисленный массив из N целых чисел.
* Отсортировать этот массив по возрастанию методом пузырька
*/
#include &lt;iostream&gt;

using namespace std;

int main()
{
int *arr; // указатель для выделения памяти под массив
int size; // размер массива

// Ввод количества элементов массива
cout &lt;&lt; «n = «;
cin &gt;&gt; size;

if (size &lt;= 0) {
// Размер масива должен быть положитлеьным
cerr &lt;&lt; «Invalid size» &lt;&lt; endl;
return 1;
}

arr = new int; // выделение памяти под массив

// заполнение массива
for (int i = 0; i &lt; size; i++) {
cout &lt;&lt; «arr = «;
cin &gt;&gt; arr;
}

int temp; // временная переменная для обмена элементов местами

// Сортировка массива пузырьком
for (int i = 0; i &lt; size — 1; i++) {
for (int j = 0; j &lt; size — i — 1; j++) {
if (arr &gt; arr) {
// меняем элементы местами
temp = arr;
arr = arr;
arr = temp;
}
}
}

// Вывод отсортированного массива на экран
for (int i = 0; i &lt; size; i++) {
cout &lt;&lt; arr &lt;&lt; » «;
}
cout &lt;&lt; endl;

delete [] arr; // освобождение памяти;

return 0;
}

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

/*
* Ввести целочисленный массив из N целых чисел.
* Отсортировать этот массив по возрастанию методом пузырька
*/
#include &lt;iostream&gt;
 

using namespacestd;

intmain()

{

int*arr;// указатель для выделения памяти под массив

intsize;// размер массива

// Ввод количества элементов массива

cout&lt;&lt;»n = «;

cin&gt;&gt;size;

if(size&lt;=){

// Размер масива должен быть положитлеьным

cerr&lt;&lt;»Invalid size»&lt;&lt;endl;

return1;

}

arr=newintsize;// выделение памяти под массив

// заполнение массива

for(inti=;i&lt;size;i++){

cout&lt;&lt;»arr = «;

cin&gt;&gt;arri;

}

inttemp;// временная переменная для обмена элементов местами

// Сортировка массива пузырьком

for(inti=;i&lt;size-1;i++){

for(intj=;j&lt;size-i-1;j++){

if(arrj&gt;arrj+1){

// меняем элементы местами

temp=arrj;

arrj=arrj+1;

arrj+1=temp;

}

}

}

// Вывод отсортированного массива на экран

for(inti=;i&lt;size;i++){

cout&lt;&lt;arri&lt;&lt;» «;

}

cout&lt;&lt;endl;

deletearr;// освобождение памяти;

return;

}

D

array qsort(array)(array _a)
{
    alias typeof(array.init) _type;
 
    array filter(bool delegate(_type) dg, array a){
        array buffer = null;
            foreach(value; a) {
 
                if(dg(value)){
                    buffer ~= value;
                }
            }
        return buffer;
    }
 
    if(_a.length <= 1) {
        return _a;
    }
    else {
        return qsort( filter((_type e){ return _a >= e; }, _a ) ) ~ _a ~
               qsort( filter((_type e){ return _a <  e; }, _a ) );
    }
 
}

Более короткий вариант с использованием стандартной библиотеки Phobos:

import std.algorithm;
 
T _qsort3(T)(T a) {
    if( a.length <= 1 )
        return a;
    else
        return _qsort3( a.filter!( e => a >= e ).array ) ~ a ~
               _qsort3( a.filter!( e => a <  e ).array );
}

Сортировка пузырьком Java

// Java программа реализации пузырьковой сортировки

class BubbleSort

{

void bubbleSort(int arr[])

{

int n = arr.length;

for (int i = 0; i < n-1; i++)

for (int j = 0; j < n-i-1; j++)

if (arr > arr)

{

// меняем местами temp и arr

int temp = arr;

arr = arr;

arr = temp;

}

}

/* Вывод массива на экран */

void printArray(int arr[])

{

int n = arr.length;

for (int i=0; i<n; ++i)

System.out.print(arr + " ");

System.out.println();

}

// Метод, тестирующий функции, приведенные выше

public static void main(String args[])

{

BubbleSort ob = new BubbleSort();

int arr[] = {64, 34, 25, 12, 22, 11, 90};

ob.bubbleSort(arr);

System.out.println("Sorted array");

ob.printArray(arr);

}

}

C# с использованием лямбда-выражений

using System;
using System.Collections.Generic;
using System.Linq;
 
static public class Qsort
    {
        public static IEnumerable<T> QuickSort<T>(this IEnumerable<T> list) where T : IComparable<T>
        {
            if (!list.Any())
            {
                return Enumerable.Empty<T>();
            }
            var pivot = list.First();
            var smaller = list.Skip(1).Where(item => item.CompareTo(pivot) <= 0).QuickSort();
            var larger = list.Skip(1).Where(item => item.CompareTo(pivot) > 0).QuickSort();
 
            return smaller.Concat(new[] { pivot }).Concat(larger);
        }
 
//(тоже самое, но записанное в одну строку, без объявления переменных)
 
        public static IEnumerable<T> shortQuickSort<T>(this IEnumerable<T> list) where T : IComparable<T>
        {
            return !list.Any() ? Enumerable.Empty<T>() : list.Skip(1).Where(
                item => item.CompareTo(list.First()) <= 0).shortQuickSort().Concat(new[] { list.First() })
                    .Concat(list.Skip(1).Where(item => item.CompareTo(list.First()) > 0).shortQuickSort());
        }
    }

Пример работы алгоритма[править | править код]

Возьмём массив с числами «5 1 4 2 8» и отсортируем значения по возрастанию, используя сортировку пузырьком. Выделены те элементы, которые сравниваются на данном этапе.

Наглядная демонстрация алгоритма.

Первый проход:

(5 1 4 2 8) (1 5 4 2 8), Здесь алгоритм сравнивает два первых элемента и меняет их местами.
(1 5 4 2 8) (1 4 5 2 8), Меняет местами, так как 5>4{\displaystyle 5>4}
(1 4 5 2 8) (1 4 2 5 8), Меняет местами, так как 5>2{\displaystyle 5>2}
(1 4 2 5 8) (1 4 2 5 8), Теперь, ввиду того, что элементы стоят на своих местах (8>5{\displaystyle 8>5}), алгоритм не меняет их местами.

Второй проход:

(1 4 2 5 8) (1 4 2 5 8)
(1 4 2 5 8) (1 2 4 5 8), Меняет местами, так как 4>2{\displaystyle 4>2}
(1 2 4 5 8) (1 2 4 5 8)

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

Третий проход:

(1 2 4 5 8) (1 2 4 5 8)
(1 2 4 5 8) (1 2 4 5 8)

Теперь массив отсортирован и алгоритм может быть завершён.

Таблица 1: Сортировка пузырьком в однопоточном режиме

1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13
1 2 3 4 5 6 7 8 9 10 11 12 13 14
1 2 3 4 5 6 7 8 9 10 11 12 13 14
2 1 3 4 5 6 7 8 9 10 11 12 13 14
2 3 1 4 5 6 7 8 9 10 11 12 13 14
2 3 4 1 5 6 7 8 9 10 11 12 13 14
2 3 4 5 1 6 7 8 9 10 11 12 13 14
2 3 4 5 6 1 7 8 9 10 11 12 13 14
2 3 4 5 6 7 1 8 9 10 11 12 13 14
2 3 4 5 6 7 8 1 9 10 11 12 13 14
2 3 4 5 6 7 8 9 1 10 11 12 13 14
2 3 4 5 6 7 8 9 10 1 11 12 13 14
2 3 4 5 6 7 8 9 10 11 1 12 13 14
2 3 4 5 6 7 8 9 10 11 12 1 13 14
2 3 4 5 6 7 8 9 10 11 12 13 1 14
2 3 4 5 6 7 8 9 10 11 12 13 14 1
2 3 4 5 6 7 8 9 10 11 12 13 14
3 2 4 5 6 7 8 9 10 11 12 13 14 1
3 4 2 5 6 7 8 9 10 11 12 13 14 1
3 4 5 2 6 7 8 9 10 11 12 13 14 1
3 4 5 6 2 7 8 9 10 11 12 13 14 1
3 4 5 6 7 2 8 9 10 11 12 13 14 1
3 4 5 6 7 8 2 9 10 11 12 13 14 1
3 4 5 6 7 8 9 2 10 11 12 13 14 1
3 4 5 6 7 8 9 10 2 11 12 13 14 1
3 4 5 6 7 8 9 10 11 2 12 13 14 1
3 4 5 6 7 8 9 10 11 12 2 13 14 1
3 4 5 6 7 8 9 10 11 12 13 2 14 1
3 4 5 6 7 8 9 10 11 12 13 14 2 1
3 4 5 6 7 8 9 10 11 12 13 14
4 3 5 6 7 8 9 10 11 12 13 14 2 1
4 5 3 6 7 8 9 10 11 12 13 14 2 1
4 5 6 3 7 8 9 10 11 12 13 14 2 1
4 5 6 7 3 8 9 10 11 12 13 14 2 1
4 5 6 7 8 3 9 10 11 12 13 14 2 1
4 5 6 7 8 9 3 10 11 12 13 14 2 1
4 5 6 7 8 9 10 3 11 12 13 14 2 1
4 5 6 7 8 9 10 11 3 12 13 14 2 1
4 5 6 7 8 9 10 11 12 3 13 14 2 1
4 5 6 7 8 9 10 11 12 13 3 14 2 1
4 5 6 7 8 9 10 11 12 13 14 3 2 1
4 5 6 7 8 9 10 11 12 13 14 1
5 4 6 7 8 9 10 11 12 13 14 3 2 1
5 6 4 7 8 9 10 11 12 13 14 3 2 1
5 6 7 4 8 9 10 11 12 13 14 3 2 1
5 6 7 8 4 9 10 11 12 13 14 3 2 1
5 6 7 8 9 4 10 11 12 13 14 3 2 1
5 6 7 8 9 10 4 11 12 13 14 3 2 1
5 6 7 8 9 10 11 4 12 13 14 3 2 1
5 6 7 8 9 10 11 12 4 13 14 3 2 1
5 6 7 8 9 10 11 12 13 4 14 3 2 1
5 6 7 8 9 10 11 12 13 14 4 3 2 1
5 6 7 8 9 10 11 12 13 14 2 1
6 5 7 8 9 10 11 12 13 14 4 3 2 1
6 7 5 8 9 10 11 12 13 14 4 3 2 1
6 7 8 5 9 10 11 12 13 14 4 3 2 1
6 7 8 9 5 10 11 12 13 14 4 3 2 1
6 7 8 9 10 5 11 12 13 14 4 3 2 1
6 7 8 9 10 11 5 12 13 14 4 3 2 1
6 7 8 9 10 11 12 5 13 14 4 3 2 1
6 7 8 9 10 11 12 13 5 14 4 3 2 1
6 7 8 9 10 11 12 13 14 5 4 3 2 1
6 7 8 9 10 11 12 13 14 3 2 1
7 6 8 9 10 11 12 13 14 5 4 3 2 1
7 8 6 9 10 11 12 13 14 5 4 3 2 1
7 8 9 6 10 11 12 13 14 5 4 3 2 1
7 8 9 10 6 11 12 13 14 5 4 3 2 1
7 8 9 10 11 6 12 13 14 5 4 3 2 1
7 8 9 10 11 12 6 13 14 5 4 3 2 1
7 8 9 10 11 12 13 6 14 5 4 3 2 1
7 8 9 10 11 12 13 14 6 5 4 3 2 1
7 8 9 10 11 12 13 14 4 3 2 1
8 7 9 10 11 12 13 14 6 5 4 3 2 1
8 9 7 10 11 12 13 14 6 5 4 3 2 1
8 9 10 7 11 12 13 14 6 5 4 3 2 1
8 9 10 11 7 12 13 14 6 5 4 3 2 1
8 9 10 11 12 7 13 14 6 5 4 3 2 1
8 9 10 11 12 13 7 14 6 5 4 3 2 1
8 9 10 11 12 13 14 7 6 5 4 3 2 1
8 9 10 11 12 13 14 5 4 3 2 1
9 8 10 11 12 13 14 7 6 5 4 3 2 1
9 10 8 11 12 13 14 7 6 5 4 3 2 1
9 10 11 8 12 13 14 7 6 5 4 3 2 1
9 10 11 12 8 13 14 7 6 5 4 3 2 1
9 10 11 12 13 8 14 7 6 5 4 3 2 1
9 10 11 12 13 14 8 7 6 5 4 3 2 1
9 10 11 12 13 14 6 5 4 3 2 1
10 9 11 12 13 14 8 7 6 5 4 3 2 1
10 11 9 12 13 14 8 7 6 5 4 3 2 1
10 11 12 9 13 14 8 7 6 5 4 3 2 1
10 11 12 13 9 14 8 7 6 5 4 3 2 1
10 11 12 13 14 9 8 7 6 5 4 3 2 1
10 11 12 13 14 7 6 5 4 3 2 1
11 10 12 13 14 9 8 7 6 5 4 3 2 1
11 12 10 13 14 9 8 7 6 5 4 3 2 1
11 12 13 10 14 9 8 7 6 5 4 3 2 1
11 12 13 14 10 9 8 7 6 5 4 3 2 1
11 12 13 14 8 7 6 5 4 3 2 1
12 11 13 14 10 9 8 7 6 5 4 3 2 1
12 13 11 14 10 9 8 7 6 5 4 3 2 1
12 13 14 11 10 9 8 7 6 5 4 3 2 1
12 13 14 9 8 7 6 5 4 3 2 1
13 12 14 11 10 9 8 7 6 5 4 3 2 1
13 14 12 11 10 9 8 7 6 5 4 3 2 1
13 14 10 9 8 7 6 5 4 3 2 1
14 13 12 11 10 9 8 7 6 5 4 3 2 1

Сортировка пузырьком

Идея алгоритма очень простая. Идём по массиву чисел и проверяем порядок (следующее число должно быть больше и равно предыдущему), как только наткнулись на нарушение порядка, тут же обмениваем местами элементы, доходим до конца массива, после чего начинаем сначала.

Отсортируем массив {1, 5, 2, 7, 6, 3}
Идём по массиву, проверяем первое число и второе, они идут в порядке возрастания. Далее идёт нарушение порядка, меняем местами эти элементы
Продолжаем идти по массиву, 7 больше 5, а вот 6 меньше, так что обмениваем из местами
3 нарушает порядок, меняем местами с 7
Возвращаемся к началу массива и проделываем то же самое

void bubbleSort(int *a, size_t size) {
	size_t i, j;
	int tmp;
	for (i = 1; i < size; i++) {
		for (j = 1; j < size; j++) {
			if (a > a) {
				tmp = a;
				a = a;
				a = tmp;
			}
		}
	}
}

Этот алгоритм всегда будет делать (n-1)2 шагов, независимо от входных данных. Даже если массив отсортирован, всё равно он будет пройден (n-1)2 раз. Более того, будут в очередной раз проверены уже отсортированные данные.

Пусть нужно отсортировать массив 1, 2, 4, 3

После того, как были поменяны местами элемента a и a нет больше необходимости проходить этот участок массива

Примем это во внимание и переделаем алгоритм

void bubbleSort2(int *a, size_t size) {
	size_t i, j;
	int tmp;
	for (i = 1; i < size; i++) {
		for (j = i; j > 0; j--) {
			if (a < a) {
				tmp = a;
				a = a;
				a = tmp;
			}
		}
	}
}

Ещё одна реализация

void bubbleSort2b(int *a, size_t size) {
	size_t i, j;
	int tmp;
	for (i = 1; i < size; i++) {
		for (j = 1; j <= size-i; j++) {
			if (a < a) {
				tmp = a;
				a = a;
				a = tmp;
			}
		}
	}
}

В данном случае будет уже вполовину меньше шагов, но всё равно остаётся проблема сортировки уже отсортированного массива: нужно сделать так, чтобы отсортированный массив функция просматривала один раз. Для этого введём переменную-флаг: он будет опущен (flag = 0), если массив отсортирован. Как только мы наткнёмся на нарушение порядка, то флаг будет поднят (flag = 1) и мы начнём сортировать массив как обычно.

void bubbleSort3(int *a, size_t size) {
	size_t i;
	int tmp;
	char flag;
	do {
		flag = 0;
		for (i = 1; i < size; i++) {
			if (a < a) {
				tmp = a;
				a = a;
				a = tmp;
				flag = 1;
			}
		}
	} while (flag);
}

В этом случае сложность также порядка n2, но в случае отсортированного массива будет всего один проход.

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

int intSort(const void *a, const void *b) {
	return *((int*)a) > *((int*)b);
}

void bubbleSort3g(void *a, size_t item, size_t size, int (*cmp)(const void*, const void*)) {
	size_t i;
	void *tmp = NULL;
	char flag;

	tmp = malloc(item);

	do {
		flag = 0;
		for (i = 1; i < size; i++) {
			if (cmp(((char*)a + i*item), ((char*)a + (i-1)*item))) {
				memcpy(tmp, ((char*)a + i*item), item);
				memcpy(((char*)a + i*item), ((char*)a + (i-1)*item), item);
				memcpy(((char*)a + (i-1)*item), tmp, item);
				flag = 1;
			}
		}
	} while (flag);

	free(tmp);
}

Функция выглядит некрасиво – часто вычисляется адрес текущего и предыдущего элемента. Выделим отдельные переменные для этого.

void bubbleSort3gi(void *a, size_t item, size_t size, int (*cmp)(const void*, const void*)) {
	size_t i;
	void *tmp = NULL;
	void *prev, *cur;
	char flag;

	tmp = malloc(item);

	do {
		flag = 0;
		i = 1;
		prev = (char*)a;
		cur  = (char*)prev + item;
		while (i < size) {
			if (cmp(cur, prev)) {
				memcpy(tmp, prev, item);
				memcpy(prev, cur, item);
				memcpy(cur, tmp, item);
				flag = 1;
			}
			i++;
			prev = (char*)prev + item;
			cur  = (char*)cur  + item;
		}
	} while (flag);

	free(tmp);
}

Теперь с помощью этих функций можно сортировать массивы любого типа, например

void main() {
	int a = {1, 0, 9, 8, 7, 6, 2, 3, 4, 5};
	int i;

	bubbleSort3gi(a, sizeof(int), 10, intSort);
	for (i = 0; i < 10; i++) {
		printf("%d ", a);
	}
	_getch();
}

Алгоритм[править | править код]

Алгоритм состоит из повторяющихся проходов по сортируемому массиву. За каждый проход элементы последовательно сравниваются попарно и, если порядок в паре неверный, выполняется перестановка элементов. Проходы по массиву повторяются N−1{\displaystyle N-1} раз или до тех пор, пока на очередном проходе не окажется, что обмены больше не нужны, что означает — массив отсортирован. При каждом проходе алгоритма по внутреннему циклу, очередной наибольший элемент массива ставится на своё место в конце массива рядом с предыдущим «наибольшим элементом», а наименьший элемент перемещается на одну позицию к началу массива («всплывает» до нужной позиции, как пузырёк в воде — отсюда и название алгоритма).

Использовать

Пузырьковая сортировка. Список был построен в декартовой системе координат, где каждая точка ( x , y ) указывает, что значение y хранится в индексе x . Затем список будет отсортирован пузырьковой сортировкой по значению каждого пикселя

Обратите внимание, что сначала сортируется самый большой конец, а меньшим элементам требуется больше времени, чтобы переместиться в правильное положение.

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

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

Жаргон Файл , который лихо звонков bogosort «архетипический извращенно ужасный алгоритм», также вызывает пузырьковую сортировку «общий плохой алгоритм». Дональд Кнут в своей книге «Искусство компьютерного программирования» пришел к выводу, что «пузырьковая сортировка, кажется, не имеет ничего, что могло бы ее рекомендовать, кроме броского названия и того факта, что она приводит к некоторым интересным теоретическим проблемам», некоторые из которых он затем обсуждает.

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

Пузырьковая сортировка также плохо взаимодействует с современным аппаратным обеспечением ЦП. Он производит как минимум вдвое больше записей, чем сортировка вставкой, вдвое больше промахов в кеш и асимптотически больше ошибочных прогнозов переходов . Эксперименты с сортировкой строк Astrachan в Java показывают, что пузырьковая сортировка примерно в пять раз быстрее сортировки вставкой и на 70% быстрее сортировки по выбору .

В компьютерной графике пузырьковая сортировка популярна благодаря своей способности обнаруживать очень маленькую ошибку (например, замену всего двух элементов) в почти отсортированных массивах и исправлять ее с линейной сложностью (2 n ). Например, он используется в алгоритме заполнения многоугольника, где ограничивающие линии сортируются по их координате x в определенной строке сканирования (линия, параллельная оси x ), а с увеличением y их порядок изменяется (два элемента меняются местами) только при пересечения двух линий. Пузырьковая сортировка — это стабильный алгоритм сортировки, как и сортировка вставкой.

Подробный разбор пузырьковой сортировки

Давайте разберем подробно как работает пузырьковая сортировка

Первая итереация (первый повтор алгоритма) меняет между собой 4 и 2 так как цифра два меньше чем четыре 2<4, повторюсь что алгоритм меняет значения между собой если, слева оно меньше чем справа. Далее происходит сверка между 4 и 3, и так как 3 меньше чем 4 (3<4) происходит обмен значениями. Потом проходит проверку между 4 и 8 и так как значение 4 меньше чем 8 то не происходит обмена, ведь уже и так всё на своих местах.

Далее сравнивается 8 и 1 и так как 1 меньше чем 8 (1<8) и оно не находиться слева то происходит обмен значениями.После это первый повтор алгоритма заканчивается, на анимации я выделил это зеленым фоном.

В итоге по окончанию работы алгоритма пузырьковой сортировки мы имеем следующий порядок числового массива: 2 3 4 1 8

и начинается второй повтор алгоритма.

Далее сравнивается 2 и 3 и так как два меньше чем три и оно находиться слева то просто идем дальше ничего не трогая. Также проверяем и 3 и 4 и тоже самое условие выполняется 3<4 и оно слева. Дальше проверяется 4 и 1 и тут мы видим что число 1<4 и не находиться слева, поэтому алгоритм меняет их местами. В крайний раз для второго повторения алгоритма проверяется 4 и 8, но тут всё в порядке, и мы дошли до конца начинаем третье повторение. Итоги для второго повторения такие : 2 3 1 4 8

Третье повторение пузырькового алгоритма начинается с сравнения 2 и 3, тут алгоритм проверяет что 2<3 и 2 находиться слева и оставляет их в покое и идет дальше. Сравнение же 3 и 1 показывает что 1 то меньше чем три, но почему то не слева и меняет их местами. Далее идет сравнение 3 и 4, тут всё в порядке и так далее до сравнения 4 и 8.

После этого получается следующий результат: 2 1 3 4 8

Как мы видим почти все цифры уже на своих местах и в порядке возрастания! Осталось только в последнем повторении пузырькового алгоритма поменять местами 2 и 1 и всё. После того как алгоритм закончил свою работу и проверил что цифры больше нельзя поменять местами он перестает работать с таким вот результатом: 1 2 3 4 8

Как улучшить пузырьковую сортировку

Ниже вы можете видеть оптимизированную версию пузырьковой сортировки.

for (int i = 0; i < 10; i++) {
bool flag = true;
for (int j = 0; j < 10 — (i + 1); j++) {
if (digitals > digitals) {
flag = false;
swap (digitals, digitals);
}
}
if (flag) {
break;
}
}

1
2
3
4
5
6
7
8
9
10
11
12

for(inti=;i<10;i++){

boolflag=true;

for(intj=;j<10-(i+1);j++){

if(digitalsj>digitalsj+1){

flag=false;

swap(digitalsj,digitalsj+1);

}

}

if(flag){

break;

}

}

Давайте посмотрим, что мы сделали для ее оптимизации:

  1. В строке 17: изменили условие внутреннего цикла на .Поэтому чтобы лишний раз не сравнивать элементы массива тратя на это время, мы решили уменьшать отрезок внутреннего цикла на 1, после каждого полного прохода внешнего цикла.
  2. Вы могли заметить, что если даже массив стал отсортирован (или сразу был отсортирован) алгоритм все равно продолжает сравнивать элементы.

Для этого в строке 5: чтобы пузырьковая сортировка останавливалась (когда массив уже стал отсортирован), мы объявили булеву переменную (ее обычно называют флаг или флажок). Еще при ее инициализации мы поместили значение , но она меняется на:

false, если результат условия в строке 4: положительный.

А в строке 9: чтобы мы могли выйти из алгоритма мы проверяем:

  • Если булева переменная равна , значит массив уже полностью отсортирован и можно выйти. Для этого используем оператор .
  • Если же значение равно , то продолжаем сортировать массив.

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

int b = digitals;
digitals = digitals;
digitals = b;

1
2
3

intb=digitalsj;

digitalsj=digitalsj+1;

digitalsj+1=b;

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

Программа упорядочения строк в алфавитном порядке[править]

 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #define N 100
 #define M 30
 int main(int argc, char* argv[]) {
    char aN];
    int n, i;
    scanf("%d", &n);
    for (i=; i<n; i++)
       scanf("%s", &ai]);
    qsort(a, n, sizeof(charM]), (int (*)(const void *,const  void *)) strcmp);
    for (i=; i<n; i++)
       printf("%s\n", ai]);
    return ;
 }

Обратите внимание на сложное приведение типов.

Функция strcmp, объявленная в файле string.h имеет следующий прототип:

int strcmp(const char*, const char*);

То есть функция получает два аргумента — указатели на кусочки памяти, где хранятся элементы типа char,
то есть два массива символов, которые не могут быть изменены внутри функции strcmp (запрет на изменение задается с помощью модификатора const).

В то же время в качестве четвертого элемента функция qsort хотела бы иметь функцию типа

int cmp(const void*, const void*);

В языке Си можно осуществлять приведение типов являющихся типами функции. В данном примере тип

int (*)(const char*, const char*); // функция, получающая два элемента типа 'const char *' и возвращающая элемент типа 'int' 

приводится к типу

int (*)(const void*, const void*); // функция, получающая два элемента типа 'const void *' и возвращающая элемент типа 'int'
Добавить комментарий

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

Adblock
detector