So I have to sort a list of people's information by their ages. In case there are people of the same ages, I have to sort them by their names alphabetically.
Here's my code:
#include <stdio.h>
#include <string.h>
struct people{
char name[30];
int age;
};
int main(){
int n, i, j, min, tmp1;
scanf("%d", &n);
struct people person[n], temp;
for(i = 0; i < n; i ){
scanf("%s%d", person[i].name, &(person[i].age));
}
// SELECTIONN SORT
for(i = 0; i < n - 1; i ){
min = i;
for(j = i 1; j < n; j ){
if (person[j].age < person[i].age ||
strcmp(person[j].name,person[min].name) < 0 && person[j].age == person[min].age){
min = j;
}
}
if(min != i){
temp.age = person[i].age;
person[i].age = person[min].age;
person[min].age = temp.age;
strcpy(temp.name, person[i].name);
strcpy(person[i].name, person[min].name);
strcpy(person[min].name, temp.name);
}
}
for(i = 0; i < n; i ){
printf("%s %d\n", person[i].name, (person[i].age));
}
}
In almost all of the cases I tried, the code works, however, on this certain input I get "Mary 15" before "Anna 15" and I have no idea why, here's the input:
5
Gilbert 35
Anna 35
Anna 15
Mary 15
Joseph 40
CodePudding user response:
I think the compare you're doing isn't right.
Change:
person[j].age < person[i].age
Into:
person[j].age < person[min].age
And, as I mentioned in my top comment, the swap can be simplified.
And, we can split up the if
to make it clearer with no loss of speed.
Here is the corrected code. It is annotated:
#include <stdio.h>
#include <string.h>
struct people {
char name[30];
int age;
};
int
main(void)
{
int n, i, j, min, tmp1;
#if 1
int dif;
#endif
scanf("%d", &n);
struct people person[n], temp;
for (i = 0; i < n; i ) {
scanf("%s%d", person[i].name, &(person[i].age));
}
// SELECTIONN SORT
for (i = 0; i < n - 1; i ) {
min = i;
for (j = i 1; j < n; j ) {
#if 0
if (person[j].age < person[i].age ||
strcmp(person[j].name, person[min].name) < 0 &&
person[j].age == person[min].age) {
min = j;
}
#else
dif = person[j].age - person[min].age;
// ages are out-of-sort
if (dif < 0) {
min = j;
continue;
}
// ages are in-sort
if (dif > 0)
continue;
// compare names only if ages are the same
dif = strcmp(person[j].name, person[min].name);
if (dif < 0) {
min = j;
continue;
}
#endif
}
if (min != i) {
// we can simplify this ...
#if 0
temp.age = person[i].age;
person[i].age = person[min].age;
person[min].age = temp.age;
strcpy(temp.name, person[i].name);
strcpy(person[i].name, person[min].name);
strcpy(person[min].name, temp.name);
#else
temp = person[i];
person[i] = person[min];
person[min] = temp;
#endif
}
}
for (i = 0; i < n; i ) {
printf("%s %d\n", person[i].name, (person[i].age));
}
}
In the code above, I've used cpp
conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Note: this can be cleaned up by running the file through unifdef -k
Here is the output of the corrected code:
Anna 15
Mary 15
Anna 35
Gilbert 35
Joseph 40