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

Я пробую различные сценарии с пузырьковой сортировкой и сортировкой выбором. Я знаю, что лучший случай для пузырьковой сортировки - O (n), если мы используем оператор break. Но скажем, даже если я не использую какой-либо оператор break, не будет никаких свопов (поскольку у нас есть условие if для него), и это должно занять столько же или меньше времени, как сортировка выбором.

Но, как ни странно, мне требуется больше времени.

Примечание. Я взял тот же набор данных (от 1 до 900 000), который уже отсортирован. А так как я использую уже отсортированный набор данных, ни в одном из алгоритмов не будет никаких обменов.

Пожалуйста, найдите программу ниже:

 package sorting;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class Sorting<Item extends Comparable>//this Item is a var/field which can only be find while creatng a object and hence it is non static
{

    List<Item> list=new ArrayList<Item>();

    public static void main(String args[])
    {

        Sorting<Integer> ss=new Sorting<Integer>();

        System.out.println("adding item logic started : "+Calendar.getInstance().getTime());
        for(int i=0;i<90000;i++)
        {
            ss.list.add(i);

        }
        System.out.println("adding item logic ended : "+Calendar.getInstance().getTime());
        //selection sort started
        Calendar c1=Calendar.getInstance();
        System.out.println(c1.getTime());
        ss.selectionSort(ss.list);

        Calendar c2=Calendar.getInstance();
        System.out.println(c2.getTime());
        System.out.println("selection sort time taken in seconds : "+(c2.getTimeInMillis()-c1.getTimeInMillis())/1000);
    //  System.out.println(ss.list);


        //bubble sort started
        ss.list=new ArrayList<Integer>();
        for(int i=0;i<90000;i++)
        {
            ss.list.add(i);

        }
        Calendar c3=Calendar.getInstance();
        System.out.println(c3.getTime());
        ss.bubbleSort(ss.list);

        Calendar c4=Calendar.getInstance();
        System.out.println(c4.getTime());
        System.out.println("bubble sort time taken in seconds : "+(c4.getTimeInMillis()-c3.getTimeInMillis())/1000);
    //  System.out.println(ss.list);
    }

    void selectionSort(List<Integer> list)
    {
        for(int i=0;i<list.size();i++)
        {
            int target=(Integer)list.get(i);
            int pos=0;

            for(int j=i+1;j<list.size();j++)
            {//System.out.println(i+"  "+j);
                if(target>(Integer)list.get(j))
                {
                    pos=j;
                    target=(Integer)list.get(j);
                }
            }
            if(pos!=0)
            {
                Integer temp=(Integer)list.get(i);
                list.set(i, (Integer)list.get(pos));
                list.set(pos, temp);


            }



        }
    }

    void bubbleSort(List<Integer> list)
    {

        for(int i=list.size()-1;i>0;i--)
        {
            int status=0;
            for(int j=0;j<=i-1;j++)
            {
                //System.out.println(i+"  "+j);
                if((Integer)list.get(j)>(Integer)list.get(j+1))
                {
                    int temp=(Integer)list.get(j+1);
                    list.set(j+1, (Integer)list.get(j));
                    list.set(j, temp);
                    status++;
                }
            }
            //if(status==0)break;
        }
    }
}

Эта программа на 85% отводит больше времени для пузырьковой сортировки, а иногда и вдвое больше, чем требуется для сортировки вставками.

adding item logic started : Fri Jun 26 02:47:13 PDT 2015
adding item logic ended : Fri Jun 26 02:47:13 PDT 2015
Fri Jun 26 02:47:13 PDT 2015
Fri Jun 26 02:47:58 PDT 2015
selection sort time taken in seconds : 44
Fri Jun 26 02:47:58 PDT 2015
Fri Jun 26 02:48:46 PDT 2015
bubble sort time taken in seconds : 56

person Onki    schedule 26.06.2015    source источник
comment
Пожалуйста, ознакомьтесь с этой ссылкой, которая содержит подробную информацию о том, почему пузырьковая сортировка занимает больше времени по сравнению с сортировкой выбором cs.stackexchange.com/questions/13106/   -  person Mudassar    schedule 26.06.2015
comment
@Mudassar Я прошел по этой ссылке и до сих пор в замешательстве. Случай, который я описал здесь, является лучшим случаем, который не требует времени на обмен. Все равно это занимает больше времени. Сортировка выбором в этом случае имеет два цикла, кроме некоторых функций присваивания, тогда как пузырьковая сортировка просто проходит через циклы, которые в идеале должны занимать меньше времени.   -  person Onki    schedule 26.06.2015
comment
В ответе в ссылке также говорится ... временная сложность зависит от реализации и работающей машины ... (и, возможно, еще больше факторов.   -  person ceekay    schedule 26.06.2015
comment
@ceekay Я выполняю оба алгоритма на одной машине и в одной программе. Но если есть какие-то проблемы с реализацией, то это то, что я хотел бы выяснить. Но я не мог найти ошибку с ним.   -  person Onki    schedule 26.06.2015
comment
Как уже упоминалось, пузырьковая сортировка требует в среднем n/4 перестановок на запись (каждая запись перемещается поэлементно из своей начальной позиции в конечную позицию, и каждая замена включает две записи), в то время как сортировка выбором требует только 1 (после минимального /максимум найден, он переставляется один раз в конец массива).   -  person Mudassar    schedule 26.06.2015
comment
@Mudassar, если вы посмотрите на программу, у нас есть условие if, чтобы решить, делать ли обмен или нет. Итак, я уже взял здесь отсортированный список, который не требует замены.   -  person Onki    schedule 26.06.2015


Ответы (4)


Ну, как я вижу по вашему коду, количество итераций в обоих алгоритмах будет одинаковым

for(int i=0;i<list.size();i++)
    for(int j=i+1;j<list.size();j++)

было бы так же, как

for(int i=list.size()-1;i>0;i--)
    for(int j=0;j<=i-1;j++)

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

В пузырьковой сортировке:

if((Integer)list.get(j)>(Integer)list.get(j+1))
{
    int temp=(Integer)list.get(j+1);
    list.set(j+1, (Integer)list.get(j));
    list.set(j, temp);
    status++;
}

поскольку список отсортирован, вы не попадете внутрь if, поэтому у вас есть два list.get(something).

В сортировке выбором:

if(target>(Integer)list.get(j))
{
    pos=j;
    target=(Integer)list.get(j);
}

но вы не попадете внутрь if, поэтому вы получите только один list.get(что-то).

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

person SaraVF    schedule 26.06.2015
comment
кстати, это то же самое, что говорил @Jan: сложность - это не то же самое, что время выполнения - person SaraVF; 26.06.2015

Вы путаете сложность и время выполнения.

Например, если у вас есть один алгоритм, который всегда занимает один час, этот алгоритм имеет сложность O(1). Второй алгоритм занимает 1 минуту для 1 элемента, 2 минуты для 2 элементов, 3 минуты для 3 элементов... Этот алгоритм имеет сложность O(n). По сложности первый алгоритм лучше, но для от 1 до 59 элементов быстрее второй алгоритм.

person Jan    schedule 26.06.2015
comment
Я понял концепции, которые вы упомянули. Но вы совершенно ошибаетесь, если говорите, что сортировка выбором лучше по сложности, а второй алгоритм лучше по времени выполнения. Просьба еще раз прочитать вопрос. Я взял тот же отсортированный набор данных от 1 до 90000 целых чисел. И тестирование обоих алгоритмов на одном и том же наборе данных. И пузырьковая сортировка занимает больше времени. И я считаю, что мы также выражаем время работы большими выражениями «о», - person Onki; 26.06.2015
comment
Сложность связана с асимптотическим поведением алгоритма, и классы с таким же асимптотическим поведением помечаются с помощью больших выражений oh. Время выполнения измеряется в секундах и зависит от множества факторов (например, ввода, процессора и т. д.). Как вы думаете, почему пузырьковая сортировка должна быть быстрее (т. е. занимать меньше секунд), чем сортировка выбором в вашем сценарии? - person Jan; 26.06.2015

Чтобы привести простой пример, здесь есть два случая. В пузырьковой сортировке

First Pass:
( 5 1 4 2 8 ) \to ( 1 5 4 2 8 ), Here, algorithm compares the first two elements, and swaps since 5 > 1.
( 1 5 4 2 8 ) \to ( 1 4 5 2 8 ), Swap since 5 > 4
( 1 4 5 2 8 ) \to ( 1 4 2 5 8 ), Swap since 5 > 2
( 1 4 2 5 8 ) \to ( 1 4 2 5 8 ), Now, since these elements are already in order (8 > 5), algorithm does not swap them.
Second Pass:
( 1 4 2 5 8 ) \to ( 1 4 2 5 8 )
( 1 4 2 5 8 ) \to ( 1 2 4 5 8 ), Swap since 4 > 2
( 1 2 4 5 8 ) \to ( 1 2 4 5 8 )
( 1 2 4 5 8 ) \to ( 1 2 4 5 8 )
Now, the array is already sorted, but the algorithm does not know if it is completed. The algorithm needs one whole pass without any swap to know it is sorted.
Third Pass:
( 1 2 4 5 8 ) \to ( 1 2 4 5 8 )
( 1 2 4 5 8 ) \to ( 1 2 4 5 8 )
( 1 2 4 5 8 ) \to ( 1 2 4 5 8 )
( 1 2 4 5 8 ) \to ( 1 2 4 5 8 )

Где как в сортировке выбором

64 25 12 22 11 // this is the initial, starting state of the array

11 25 12 22 64 // sorted sublist = {11}

11 12 25 22 64 // sorted sublist = {11, 12}

11 12 22 25 64 // sorted sublist = {11, 12, 22}

11 12 22 25 64 // sorted sublist = {11, 12, 22, 25}

11 12 22 25 64 // sorted sublist = {11, 12, 22, 25, 64}

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

person Mudassar    schedule 26.06.2015
comment
Пожалуйста, проверьте условие, что я уже предоставляю отсортированный набор данных для обоих алгоритмов, что не приведет к обмену в обоих алгоритмах. - person Onki; 26.06.2015
comment
Даже если своп не происходит, это не означает, что он не будет выполнять необходимые сравнения для идентификации свопа. - person Mudassar; 26.06.2015

Ты говоришь:

«Но скажем, даже если я не использую никакого оператора break, никаких свопов не будет (поскольку у нас есть условие if для него), и это должно занять столько же или меньше времени, как сортировка выбором».

В своем коде вы комментируете оператор break во внешнем цикле:

//if(status==0)break;

Без оператора break алгоритм/код равен O(n^2), и вы не получаете никакой выгоды от его сортировки.

person Peter Webb    schedule 27.06.2015