#c #sorting
#c #сортировка
Вопрос:
Я пытаюсь сортировать слова при добавлении их в список на C . Я должен использовать списки, и я не могу использовать функцию «sort ()».
У меня есть текстовый файл с несколькими словами (каждое слово находится на новой строке).
До сих пор я выяснил, как собирать слова и добавлять их в список:
fstream myfile(fileName);
if(!myfile) { // Test if file open
cout<<"Error opening file"<< endl;
return false;
}
while (getline(myfile, line)){ //loops through and gets sayings
l.push_back(line);
}
Слова просто добавляются в том порядке, в котором они находятся в файле. Что я хочу сделать, это проверить первую букву слова, а затем поместить ее в соответствующую позицию в списке, вместо того, чтобы просто добавлять их в конец списка.
Заранее спасибо!
Подробная информация:
Я полагаю, что для этого я должен использовать итератор.
Я знаю, как использовать итератор для отображения списка:
for (list<string>::iterator it=l.begin(); it != l.end(); it)
cout << *it << endl;
Как я могу использовать это для сравнения значений перед их добавлением? Я пытался использовать итератор, чтобы получить первую букву слова, используя (*it)[0]
, но это недопустимый синтаксис.
Комментарии:
1. Может быть, использовать
std::multiset
(илиstd::set
)? Или это что-то, что вам тоже не позволено делать?2. Что я хочу сделать, это проверить первую букву слова, а затем поместить ее в соответствующую позицию в списке, — Как только проверка первой буквы считается «сортировкой»?
3.Я должен использовать списки, и я не могу использовать функцию «sort ()».—
std::list
Поставляется сsort()
функцией. Почему вы не можете использовать его, если вы уже используетеstd::list
?? Я видел некоторые действительно сумасшедшие требования, предъявляемые учителями, но это, должно быть, одно из самых безумных, о которых я когда-либо слышал.4. не
push_back
делайте этого. Для каждого слова перебирайте список, пока не найдете первое слово с первой буквой первая буква после слов первая буква, а затем вставьте слово перед словом, которое вы только что нашли.5. @user4581301 это достойно сожаления. И это еще более неприятно, когда я думаю, что это может быть ожидаемое решение / лучшее, что вы можете сделать с требованиями, как указано в OP.
Ответ №1:
Я бы добавил итератор
std::list<string> mylist;
std::list<string>::iterator it; //now I can move through the list using this kind of like an index
for (it=mylist.begin(); it!=mylist.end(); it)
{
if( line.compare(*it) >= 0) //If the line belongs before what *it is pointing to
{
mylist.insert(it,line);
break;
}
}
узнайте больше о string::compare в http://www.cplusplus.com/reference/string/string/compare /
узнайте больше о вставке в список на http://www.cplusplus.com/reference/list/list/insert /
Комментарии:
1. Я едва только поцарапал поверхность с C , но только что познакомился с итераторами от одноклассника. Все, что я вижу здесь, имеет смысл, кроме одной детали, которая является line.compare( it) почему » означает? Я хочу думать, что это указатель, но тогда для меня не имеет смысла, почему мы должны использовать указатель
2. @BrettReinhard — итератор фактически является указателем, поэтому вы используете * его для доступа (чтения или записи) к элементу.
3. @rcgldr спасибо, что прояснили это. Итак, по существу ли это ссылка на адрес, аналогичный тому, как вы передаете массив?
4. @BrettReinhard — не совсем. Обычно внутренний формат std::list представляет собой двусвязный список, поэтому обычно вы не можете индексировать (при условии, что нет разумной перегрузки оператора, std::list не имеет итераторов произвольного доступа). Итак, он продвигается по следующему указателю и — выполняет резервное копирование по предыдущему указателю. std::list функции: begin() возвращает итератор к первому элементу, back() возвращает итератор к последнему элементу, end() возвращает итератор сразу после последнего элемента.
5. @BrettReinhard — верно, есть накладные расходы на связь между узлами. Последовательные узлы в списке могут быть случайным образом разбросаны по памяти, что негативно сказывается на кешировании и делает сканирование относительно медленным. Сортировку лучше всего выполнять с помощью сортировки слиянием снизу вверх с небольшим массивом указателей на узлы, как показано в примере wiki .
Ответ №2:
Предполагая, что вы можете использовать std::set
или std::multiset
:
multiset<string> l;
while (getline(myfile, line)){ //loops through and gets sayings
l.insert(line);
}
Это добавит все слова и отсортирует их автоматически. Основное различие между multiset
и set
заключается в том, что первое допускает дублирование, а второе — нет.
Затем вы можете выполнить итерацию l
с for
помощью цикла:
for(string constamp; s : l) {
cout << s << endl;
}