Я новичок в C ++ и пытаюсь реализовать алгоритм сортировки выбора в качестве упражнения.
Я дошел до того, что пытался поменять местами значение в самой левой ячейке памяти со значением в ячейке памяти минимума несортированной части вектора.
(См. Код ниже.)
Можно ли использовать std::vector::iterator
для того, чтобы изменить значения, содержащиеся в векторе, к которому он принадлежит?
#include <vector>
#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;
template<typename T>
ostream& operator<<( ostream& out, vector<T> thisVector ) {
for( size_t i = 0, choke = thisVector.size(); i < choke; i++ )
out << thisVector[ i ] << " ";
return out;
}
template<typename T>
typename vector<T>::iterator get_minimum( vector<T>& thisVector, typename vector<T>::iterator pos, typename vector<T>::iterator end ) {
T min = *pos;
typename vector<T>::iterator minPos;
while ( pos != end ) {
if ( *pos < min ) {
min = *pos;
minPos = pos;
}
pos++;
}
return minPos;
}
template<typename T>
void swap( typename vector<T>::iterator pos, typename vector<T>::iterator& minPos ) {
T temp = *pos;
// I was hoping the following two lines would modify the vector passed to selection_sort
pos = *minPos;
minPos = temp;
return;
}
template<typename T>
void selection_sort( vector<T>& thisVector, typename vector<T>::iterator pos ) {
typename vector<T>::iterator end = thisVector.end();
typename vector<T>::iterator minPos = get_minimum( thisVector, pos, end );
cout << "Swap was given this " << *pos << " " << *minPos << endl;
swap( pos, minPos );
cout << "and returned this " << *pos << " " << *minPos << endl;
return;
}
int main() {
// initialize random seed
srand (time(NULL));
// Create data stub
vector<int> myThing;
do {
myThing.push_back( rand() % 20 );
} while ( myThing.size() <= 10 );
cout << "Unsorted: " << myThing << endl;
selection_sort( myThing, myThing.begin() );
cout << " Sorted: " << myThing << endl;
return 0;
}
Проблема, с которой вы сталкиваетесь при обмене значениями, на которые указывают итераторы, вызвана тем, что компилятор подхватывает std::swap
с помощью ADL. std::swap
просто меняет местами то, на что указывают итераторы, но не значения, на которые указывают итераторы.
Если вы называете функцию myswap
и позвонить myswap
вместо swap
вы, вероятно, увидите сообщения об ошибках компилятора. Проверять, выписываться мой вопрос по теме.
Вместо этого, если вы используете:
template<typename Iterator>
void myswap(Iterator pos1,
Iterator pos2)
{
auto temp = *pos1;
*pos1 = *pos2;
*pos2 = temp;
}
все должно работать. Вот рабочая программа, использующая g ++ 4.8.2.
#include <iostream>
#include <vector>
#include <iterator>
template<typename Iterator>
void myswap(Iterator pos1, Iterator pos2)
{
auto temp = *pos1;
*pos1 = *pos2;
*pos2 = temp;
}
void testMyswap()
{
std::cout << "\nTesting myswap()\n";
std::vector<int> v{1, 2, 3, 4, 5, 6};
std::vector<int>::iterator iter = v.begin();
std::vector<int>::iterator temp = std::next(iter, 2);
std::cout << "Values iterators point to before swap.\n";
std::cout << *iter << " " << *temp << std::endl;
myswap(iter, temp);
std::cout << "Values iterators point to after swap.\n";
std::cout << *iter << " " << *temp << std::endl;
std::cout << "The vector after the swap.\n";
for ( iter = v.begin(); iter != v.end(); ++iter )
{
std::cout << *iter << " ";
}
std::cout << std::endl;
}
int main()
{
testMyswap();
return 0;
}
Выход
Тестирование myswap () Итераторы значений указывают на перед свопом. 1 3 Значения итераторов указывают после перестановки. 3 1 Вектор после свопа. 3 2 1 4 5 6
Да, это возможно. Учитывая итератор iter
, *iter
может быть назначено как обычное lvalue для изменения основного контейнера, например:
*iter = 5; // The value in the container that `iter` points to is now 5.
Это возможно. И вот хитрость, чтобы сделать вашу жизнь проще.
Своп уже определенная функция.
добавлять #include <utility>
и вы получите swap
бесплатно. Многие объекты C ++ определяют специализации подкачки. Например, std::vector
реализует обмен между двумя векторами, просто меняя указатели.
Для вашего кода вы можете удалить определение swap и использовать swap(*pos, *minPos)
Мне нужно было назвать свой код: будучи совсем новым новичком, я не осознавал std::swap(iter, iter)
уже существует, и был призван — а не мой swap
функция.
Тем не менее, после того, как я поместил пространство имен в свой код, ответ jwodder доказал свою эффективность: используя *iter
скорее, чем iter
мой код скомпилирован и вектор был правильно изменен swap
,