#c #string #c-strings #bubble-sort
#c #строка #c-строки #пузырьковая сортировка
Вопрос:
#include<stdio.h>
#include<string.h>
int main()
{
setbuf(stdout,NULL);
char str1[50][50],temp[50];
int lim,i,j,res;
printf("Enter the number of strings: ");
scanf("%d",amp;lim);
for(i=0;i<lim;i )
{
scanf("%s",str1[i]);
}
for(i=0;i<lim;i )
{
for(j=1;j<lim-1;j )
{
res=strcmp(str1[i],str1[j]);
if(res==1)
{
strcpy(temp,str1[i]);
strcpy(str1[i],str1[j]);
strcpy(str1[j],temp);
}
}
}
for(i=0;i<lim;i )
{
puts(str1[i]);
}
return 0;
}
Я пытаюсь использовать пузырьковую сортировку для сортировки строк, введенных пользователем. Но результат получается неправильным.
Есть ли какая-либо ошибка в моей логике в if
инструкции?
Комментарии:
1. @h0r53 Не то чтобы это добавило какой-либо безопасности коду. Проблема начинается с
scanf
.2. У @h0r53
strncpy
есть свои проблемы. Особенно скопированная строка может оказаться без нулевого разделителя.3. @Jabberwocky Я видел людей, которым сказали заменить
strcpy(str1, str2)
наstrncpy
.. И они это сделалиstrncpy(str1, str2, strlen(str2))
(ну, иногда заботились о 1) 😀4. При пузырьковой сортировке вы сравниваете соседние элементы и меняете местами, когда это необходимо. Этот код начинается с
i
и сравниваетсяstr1
сi
каждым другим элементом. После того, как вы поменялиstr1[i]
местами что-то другое, вы больше не сравниваете это с соседними элементами, потому чтоi
это будет пропущено на следующей итерации цикла. Это логический недостаток.5. Подсказка: не уверен, что проблема в этом: но
if (res==1)
это неправильно и должно бытьif (res>0)
.strcmp
Внимательно прочитайте документацию, особенно ту часть, которая касается возвращаемого значения.
Ответ №1:
Как заметил @h0r53 в комментариях, то, что вы реализовали, [вообще] не является пузырьковой сортировкой. Это почти сортировка по выбору, но она имеет неправильные границы итерации внутреннего цикла, которые кажутся несколько напоминающими пузырьковую сортировку. Комбинация нарушена. С точки зрения сортировки выборки это неправильно, потому что вы никогда не рассматриваете последний элемент, и это неэффективно, потому что вы без необходимости пересматриваете ведущие элементы, которые уже были отсортированы.
Ключевая часть алгоритмически правильной версии сортировки выбора может выглядеть следующим образом:
for (i = 0; i < lim; i ) {
for (j = i 1; j < lim; j ) { // These bounds are changed vs. the original
// Compare each subsequent element with element i:
res = strcmp(str1[i], str1[j]);
if (res > 0) {
strcpy(temp, str1[i]);
strcpy(str1[i], str1[j]);
strcpy(str1[j], temp);
}
}
}
Альтернативно, это была бы алгоритмически правильная версия пузырьковой сортировки:
// for (i = 0; i < lim; i ) { // particularly inefficient; note: no i in the loop body
for (; lim > 1; lim--) {
for (j = 0; j < lim - 1; j ) { // Almost, but not quite, the same as the original
// Compare each element but the last with the following one:
res = strcmp(str1[j], str1[j 1]);
if (res > 0) {
strcpy(temp, str1[j]);
strcpy(str1[j], str1[j 1]);
strcpy(str1[j 1], temp);
}
}
}
Эта реализация уменьшается lim
на 1 на каждой итерации внешнего цикла, потому что каждая итерация приведет к тому, что следующий по величине элемент переместится в правильное конечное положение, где его не нужно будет рассматривать снова.
Ответ №2:
Ваш код может выполняться, если вы измените инструкцию сортировки, как показано ниже: Из:
for(i=0;i<lim;i )
{
for(j=1;j<lim-1;j )
{
res=strcmp(str1[i],str1[j]);
if(res==1)
{
strcpy(temp,str1[i]);
strcpy(str1[i],str1[j]);
strcpy(str1[j],temp);
}
}
}
Для
while (cont) {
cont = 0;
for (int i = 0; i < lim - 1; i )
{
res=strcmp(str1[i],str1[i 1]);
if (res > 0)
{
strcpy(temp,str1[i]);
strcpy(str1[i],str1[i 1]);
strcpy(str1[i 1],temp);
cont = 1;
}
}
}