Почему мой код сортировки слиянием медленнее, чем сортировка вставками

Я пытался сделать сортировку слиянием и сортировку вставкой и сравнить результат времени для них обоих. И от размера ввода массива от 10 до 10000 сортировка слиянием была медленнее, чем сортировка вставками.

это код для сортировки вставками

vector<int> insertion_sort(vector<int> vec)
{
    for(int i = 1 ; i <vec.size();i++)
    {
        int j = i-1;
        while(j>=0 && vec[j+1]<vec[j] )
        {
            int x = vec[j+1];
            vec[j+1] = vec[j];
            vec[j--] = x;
        }
    }
    return vec;
}

А это код сортировки слиянием

vector<int> merge(vector<int> left,vector<int> right)
{
    int i = 0;
    int j = 0;
    vector<int> ret(left.size()+right.size());
    int it = 0;
    for(; i <left.size() && j<right.size();)
    {
        if(left[i]<right[j])
            ret[it++]=(left[i++]);
        else if(right[j]<left[i])
            ret[it++]=(right[j++]);
        else ret[it++]=(left[i++]),ret[it++]=(right[j++]);
    }
    for(;i<left.size();)
        ret[it++]=(left[i++]);
    for(;j<right.size();)
        ret[it++]=(right[j++]);
    return ret;
}
vector<int> merge_sort(vector<int> A,int start,int end)
{
    if(start >= end) 
    {
        vector<int> v(1);
        v[0]=(A[start]);
        return v;
    }
    int mid = (start+end )/ 2;
    vector<int> left = merge_sort(A,start,mid);
    vector<int> right = merge_sort(A,mid+1,end);
    return merge(left,right);
}

и, наконец, вот как я вызываю их всех и вычисляю время

int main()
{
    vector<int> rand_vec;

    srand(time(0));
    for(int i = 0 ; i <SIZE;i++)
    {
        rand_vec.push_back(rand()%SIZE);
    }
    int t = clock();
    vector<int> merge_sorted = merge_sort(rand_vec,0,rand_vec.size()-1);
    puts("");
    printf("merge sort time = %d\n",clock() - t );


    t = clock();
    vector<int> insertion_sorted = insertion_sort(rand_vec);
    puts("");
    printf("insertion sort time = %d\n",clock() - t );
    return 0;
}

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

Спасибо.


person AerRayes    schedule 12.10.2013    source источник
comment
Что такое РАЗМЕР? Если он маленький, это может быть ваша проблема.   -  person templatetypedef    schedule 12.10.2013
comment
Я больше любитель Java, но не передает ли вектор в качестве параметра его копию (конструктор копирования)? Это было бы тяжело.   -  person SJuan76    schedule 12.10.2013
comment
@templatetypedef Я пробовал SIZE от 5 до 100000, и каждый раз сортировка слиянием занимает больше времени   -  person AerRayes    schedule 12.10.2013
comment
@ SJuan76 Я тоже боялся, что проходящие векторы могут создать дилемму. в то же время я хотел сделать это на этот раз с помощью векторов   -  person AerRayes    schedule 12.10.2013
comment
Вместо vector<int> используйте *vector<int> (и соответствующим образом измените остальную часть кода).   -  person SJuan76    schedule 12.10.2013
comment
или даже лучше (по возможности const) ссылка vector<int>& ;)   -  person lolando    schedule 12.10.2013
comment
и, кстати, используйте reserve для своего вектора, прежде чем использовать тысячи push_back, когда вы заранее знаете размер   -  person lolando    schedule 12.10.2013
comment
@lolando Спасибо. Это именно то, что я пробовал после того, как SJuan76 сказал, что И это действительно значительно сократило время.   -  person AerRayes    schedule 12.10.2013
comment
@lolando Раньше я отталкивал весь код сортировки слиянием .. затем я заменил его оператором [] для более быстрого доступа после знания размера .. но зачем мне использовать реверс?   -  person AerRayes    schedule 12.10.2013
comment
reserve, а не reverse. Укажите окончательный размер, чтобы вектор не увеличивался каждые несколько входных данных.   -  person SJuan76    schedule 12.10.2013
comment
@ SJuan76 Строго говоря, reserve устанавливает емкость, а не размер   -  person lolando    schedule 12.10.2013


Ответы (4)


чтобы обобщить ответы, предоставленные до сих пор:
- используйте ссылку (или указатель ), чтобы избежать копирования векторов:
- используйте reserve, когда вы заранее знаете размер, прежде чем использовать тысячи push_back (так что вам не нужно динамически перераспределять всякий раз, когда емкость превышена)
- вы можете сделать const vector<int>& merge_sorted = ..., чтобы избежать копирования при возврате вашего вектора

person lolando    schedule 12.10.2013
comment
Иногда люди беспокоятся о постепенном увеличении стоимости std::vector. Раньше я беспокоился об этом и использовал резерв() для оптимизации роста. Измерив свой код и неоднократно сталкиваясь с трудностями в поиске преимуществ резерва() в производительности в реальных программах, я перестал использовать его, за исключением случаев, когда это необходимо, чтобы избежать аннулирования итератора (редкий случай в моем коде). Еще раз: измерьте, прежде чем оптимизировать. -- Бьерн Страуструп (stroustrup.com/bs_faq2.html#slow-containers ) - person rici; 12.10.2013
comment
Я не думаю, что резервирование вредит удобочитаемости или ремонтопригодности кода. Во всяком случае, это документально подтверждает, что размер известен заранее. Может быть, никаких огромных преимуществ, но вы могли бы также сделать это. - person Teimpz; 29.11.2016

Передача векторов по ссылке, а не по значению имеет огромное значение. На моей машине с SIZE=50000, скомпилированной с -O3, раньше:

merge sort time = 5730000

insertion sort time = 1470000

После:

merge sort time = 10000

insertion sort time = 1470000

Я изменил только две строки:

vector<int> merge(const vector<int> &left,const vector<int> &right)
vector<int> merge_sort(const vector<int> &A,int start,int end) 
person mrip    schedule 12.10.2013

Помимо ответа mrip о ссылках, имейте в виду:

«Сортировка вставками — один из самых быстрых алгоритмов для сортировки очень маленьких массивов, даже быстрее, чем быстрая сортировка. В лучшем случае ввод — это массив, который уже отсортирован. В этом случае сортировка вставками имеет линейное время выполнения. массив отсортирован в обратном порядке."

person Denes    schedule 12.10.2013

Сортировка слиянием не обязательно медленнее, чем сортировка вставками. Время, затрачиваемое сортировкой вставками на сортировку «n» элементов, пропорционально n в квадрате (nn), в то время как время, затрачиваемое на сортировку слиянием, пропорционально n, умноженному на log n по основанию 2 (nlgn). Таким образом, вставка sort быстрее, чем сортировка слиянием в одном коде, а сортировка слиянием в других

person Swarup Hegde    schedule 29.11.2016