|
(Bubble Sort) |
(BiDirectional Bubble Sort) |
|
(Shells Sort) |
(Quick Sort) |
Самый известный и самый медленный вид сортировки.
Его популярность это следствие запоминающегося
названия и простота.
Пузырьковая сортировка основана на методе перестановок.
Алгоритм - это постоянное сравнение элемента с
соседними элементами и перестановка их при необходимости.
Элементы массива при этом уподобляются всплывающим
пузырькам в сосуде с водой (что и можно заметить на аплете)
Алгоритм состоит из двух циклов. Внешний задает область
поиска а внутренний в этой области выполняет
перестановки между соседними элементами.
После одного прохода внешнего цикла
вначале массива оказывается один элемент
(самый маленький в нашем случае), после чего
эта (верхная) часть массива уже не учавствует
в сортировке. Потом внутренний цикл выдает нам
еще один элемент из нижней части массива
(после первого прохода это весь массив, кроме одного
отсортированного элемента в верхней части)
и ставит его на второе место, когда верхний цикл
идет по третьему кругу внутренний сравнивает
и выбирает самый мелкий элемент уже из всех
кроме первых двух верхних и т.д.
После count-1 проходов (count размер массива) внизу
остается только один (самый большой ) элемент и
массив отсортирован.
Анализируя алгоритмы сортировки надо принимать
во внимание количество произведенных сравнений
и перестановок.
Для пузырьковой сортировки это:
1/2*n*(n-1) - число сравнений.
3/4*n*(n-1) - среднее число перестановок.
3/2*n*(n-1) - максимальное возможное число
перестановок.
Пузырьковая сортировка является квадратичным алгоритмом
по числу сравнений и перестановок относительно числа
сортируемых элементов. И, крайне неэффективной.
Ниже приведен пример алгоритма на языке С++,
если вас смущает шаблонная форма сего то просто
пропустите "template < class Stype >" и в
функции вместо Stype вставьте свой тип данных,
к примеру float.
// BubbleSort
template < class Stype > void bubble( Stype *item, int count)
{
register int i, j;
Stype t;
for( i=1; i =i ; j--){
if (item[j-1]>item[j]){
t = item[j-1];
item[j-1] = item[j];
item[j] = t;
}
}//for j
}//for i
}
Cие произведение искусства принципиально ни чем не отличается от простой Пузырьковой сортировки, только сравнение идет в обе стороны (как и видно на примере) Никакого существенного выигрыша в этом алгоритме нет, но можно поморочить голову тем кто верит наслово. Единственный плюс - это более быстрое понимание того что массив уже отсортирован и ничего больше сравнивать не надо, то есть выход из сортировки в случае если перестановок за проход не произошло. Сам я это "произведение искусства" нашел в примерах поставляемых с JDK, и сюда поместил просто чтобы лишний раз показать что Пузырек плох в любой вариации.
//BiDirBubbleSort
template < class Stype > void bubble( Stype *item, int count)
{
int j, flipped;
int limit= count ;
int st = -1;
Stype temp;
while (st < limit){
flipped = 0;
st++;
limit--;
for (j = st; j < limit; j++){
if (item[j] > item[j + 1]) {
temp = item[j];
item[j]=item[j+1]
item[j+1]=temp;
flipped = 1;
}
}
if (!flipped) {
return;
}
for (j = limit; --j >= st;) {
if (item[j] > item[j + 1]) {
temp = item[j];
item[j]=item[j+1]
item[j+1]=temp;
flipped = 1;
}
}
if (!flipped) return;
}
}
template < class Stype > void shell( Stype *item, int count)
{
register int i, j, gap, k;
Stype t;
char a[] = {9, 5, 3, 2, 1};
for (k = 0; k < 5; k++){
gap = a[k];
for (i = gap - 1; i < count; i++)
t = item[i];
for(j=i-gap;j > =0 && item[j] > x;j-=gap)
item[j+gap] = item[j];
item[j+gap] = t;
}
}
template < class Stype > void quicksort(Stype *item,int count)
{
int i, j;
Stype center;
Stype x;
i = left;
j = right;
center = item[ (left+right)/2 ];
while (i < = j )
{
while ( (item[i] < center)&&(i < right) ) i++;
while ( (item[j] > center)&&(j > left ) ) j--;
if ( i<=j ){
x = item[i];
item[i] = item[j];
item[j] = x;
i++; j--;
}
}
if (left < j) quicksort(left , j);
if (right > i) quicksort(i, right);
}