2013-08-26 2 views
1

Я создаю это, чтобы лучше понять алгоритмы сортировки и общие функции. Я реализовал базовый алгоритм сортировки вставки, и я пытаюсь заставить его работать с несколькими структурами данных (списки и массивы, по крайней мере).C++ generic insertion sort

Поскольку я могу получить доступ к таким спискам: list [N], чтобы получить значение, я думаю, что мне нужно использовать итераторы. Поэтому я пытаюсь преобразовать свое решение. Вот основная вставка рода алгоритм Я пытаюсь изменить:

int *insertionsort(int *a) 
{ 
    for (int i = 1; i<length(a); ++i) 
    { 
    int k = a[i]; 
    int j = i-1; 
    { 
     while (j>=0 && a[j] > k) 
     { 
     a[j+1] = a[j--]; 
     } 
    a[j+1] = k; 
    } 
    return a; 
} 

А вот то, что я до сих пор для общей версии:

template <class T> 
T insertionsort(T a) 
{ 
    for (auto i = a.begin()+1; i<a.end(); ++i) 
    { 
    auto k = i; 
    auto j = i-1; 
    while (j>=a.begin() && *j>*k) 
    { 
     (j + 1) = j--; 
    } 
    (j + 1) = k; 
    } 
    return a; 
} 

Unfortunatley Я не могу показаться, чтобы получить это родовое функция для правильной сортировки. Я смотрел на это довольно долго, не повезло. Идеи?

+0

У вас возникли ошибки? – 0x499602D2

+1

Что случилось с 'strlen (a)'? Это совсем не так, как вы должны получить длину массива int; вам нужно передать длину массива. – user2357112

+0

'(j + 1) = ничего' не имеет смысла. Вы имели в виду разыменовать итератор? – user2357112

ответ

6

Размещено только для ссылки ОП и вряд ли будет жить долго. Если вы так склонны использовать C++ 11 и не хотите печатать, это может сделать трюк.

template<typename Iter> 
void insertion_sort(Iter first, Iter last) 
{ 
    for (Iter it = first; it != last; ++it) 
     std::rotate(std::upper_bound(first, it, *it), it, std::next(it)); 
} 

Relavent ссылки для функций, используемых:

std::upper_bound, std::next и std::rotate. Наслаждаться.

+0

Когда я увидел это в комментарии @ nosid, я подумал: «WTF, вставка сортировки в две строки!» * – Manu343726

+0

+1 для использования двоичного поиска для сканирования уже отсортированной подпоследовательности. – Cubbi

3

Я думаю, что вы путаетесь с разыменованием итераторов/указателей. Это должно работать:

template <class T> 
T insertionsort(T a) 
{ 
    if(a.begin() == a.end()) // return a when it's empty 
     return a; 
    for(auto i = a.begin() + 1; i < a.end(); ++i) 
    { 
     auto k = *i; // k is the value pointed by i 
     auto j = i - 1; 
     while(j >= a.begin() && *j > k) 
     { 
      *(j + 1) = *j; // writen in 2 lines for clarity 
      j--; 
     } 
     *(j + 1) = k; 
    } 
    return a; 
} 
+2

Я думаю, что UB переместит 'j' за левый конец' a'. Если 'a' пуст,' a.begin() + 1' также является UB. – user2357112

+0

Большое вам спасибо, у меня было подобное решение в один момент, но я не разыскивал i при назначении его авто k. Это решение отлично работает. –

+0

@ user2357112 Вы правы. Я просто просто фиксировал разыменование здесь. – pkacprzak

3

Ее лучше, для более общего решения, чтобы передать диапазон, который будет отсортирован вместо вещей, чтобы быть отсортированы, так как стандартные алгоритмы, такие как std::sort() сделать:

template <typename BIDIRECTIONAL_ITERATOR> 
void insertionsort(BIDIRECTIONAL_ITERATOR begin , BIDIRECTIONAL_ITERATOR end) //Note that the iterators 
{                    //are passed by value 
    if(begin == end) return; //If the range is empty, abort 

    for(auto i = begin + 1; i < end; ++i) 
    { 
     auto j = i - 1; 
     bool flag = false; //Used to abort the loop after j == begin case 
     while(!flag && (j != begin || (flag = j == begin)) && *j > *i) 
     { 
      *(j + 1) = *j; 
      j -= !flag; //If j == begin, don't decrement (Without branch) 
     } 
     *(j + 1) = *i; 
    } 
} 

Функция - это процедура, не возвращает ничего, сортирует исходный диапазон.

+0

Я думаю, вы можете уменьшить это на двунаправленный итератор, используя 'std :: next' (C++ 11) вместо' + 1', 'i! = End' и' j! = Begin' (хотя я предполагаю, что там должна быть специальная проверка, поскольку «начало-1» может быть UB для некоторых случаев). – dyp

+0

@WhozCraig Я исправлял это сейчас :) Спасибо – Manu343726

+0

Есть ли больше преимуществ для передачи в диапазоне данных, а затем для подмножества данных для сортировки? –

Смежные вопросы