问题
I need to do is read in an input file into a linked list. Part of the file is:
NameA, 25
NameB, 33
NameC, 23
NameD, 39
And after i need to sort by the number (bubble sort) and write it to another file.
Here is what i have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node{
char name[20];
int number;
struct node *next;
struct node *prev;
}*head;
int main(void) {
struct node *temp;
temp = malloc(sizeof(struct node));
temp->next = NULL;
head = temp;
FILE *ifp;
char fnamer[100] = "";
char line[128];
// printf("\n\nPlease Enter the Full Path of the file: \n");
// scanf("%s",&fnamer);
ifp = fopen("mintaadatok.txt", "r");
if (ifp == NULL) {
printf("\n%s\" File NOT FOUND!", fnamer);
exit(1);
}
int c = 0;
char buffer[1024];
memset(buffer, 0, 1024);
while (c < 15) {
fgets(buffer, 1024, ifp);
sscanf(buffer, "%19[^,], %d", temp->name, &temp->number);
printf("%d %s %d\n", c, temp->name, temp->number);
temp->next = malloc(sizeof(struct node));
temp = temp->next;
temp->next = NULL;
c++;
}
int i,step;
for (temp = head; temp; temp = temp->next) {
printf("%s", temp->name);
printf("%d\n", temp->number);
for(step=0;step<10-1;++step)
for(i=0;i<10-step-1;++i)
{
temp->next = malloc(sizeof(struct node));
if(temp->number>temp->next)
{
temp=temp->number;
temp->number=temp->next;
temp->next=temp;
}
}
}
printf("In ascending order: ");
}
Can you help me to sort these data?
回答1:
while(c<10)
{
fgets(buffer, 1024, ifp);
sscanf(buffer, "%19[^,], %d", temp->name, &temp->id);
...
}
The file appears to have 4 entries, not 10. A better way to read the file is using while(fgets(buffer, 1024, ifp)){...}
This will stop when there are no more lines to be read. It doesn't matter here because the memory is freed as soon as you exit main
but in a practical application you run the code in different functions and you have to free the memory.
The linked list is not entirely correct because you are calling an extra malloc
, this memory cannot be freed.
Sorting a linked list using bubble sort is not trivial. A better way is to read the file in to an array of node
, using realloc
. Then use bubble sort on the array. Alternatively, you can convert the linked-list to an array (pointless!)
Otherwise, to use bubble sort on linked list you can make two loops to walk the list, then compare and change the values of each node.
The example below inserts the entries at the head of the list (it doesn't matter since the list is being sorted) and runs bubble sort:
struct node
{
char name[20];
int id;
struct node *next;
}*head;
int main(void)
{
FILE *ifp = fopen("mintaadatok.txt", "r");
if (!ifp)
{
printf("file error\n");
return 0;
}
char buffer[1024];
memset(buffer, 0, 1024);
while(fgets(buffer, 1024, ifp))
{
struct node *temp = malloc(sizeof(struct node));
temp->next = NULL;
if(sscanf(buffer, "%19[^,], %d", temp->name, &temp->id) != 2)
{
free(temp);
break;
}
if(!head)
{
head = temp;
}
else
{
temp->next = head;
head = temp;
}
}
//bubble sort here:
struct node *loop1 = head;
while(loop1)
{
int swapped = 0;
struct node *loop2 = loop1->next;
while(loop2)
{
if(loop1->id > loop2->id)
{
//swap the values for `name` and `id`
//but don't change the `next` pointers
char name[20];
strcpy(name, loop1->name);
strcpy(loop1->name, loop2->name);
strcpy(loop2->name, name);
int id = loop1->id;
loop1->id = loop2->id;
loop2->id = id;
swapped = 1;
}
loop2 = loop2->next;
}
//if there were no swaps then list is already sorted
if (!swapped)
break;
loop1 = loop1->next;
}
//print the list:
loop1 = head;
while(loop1)
{
printf("%s %d\n", loop1->name, loop1->id);
loop1 = loop1->next;
}
return 0;
}
回答2:
We beginners should help each other.:)
I did not look through all your code. However it is obviously incorrect for example due to the incorrect order of allocations of nodes in this loop
while (c < 15) {
fgets(buffer, 1024, ifp);
sscanf(buffer, "%19[^,], %d", temp->name, &temp->number);
printf("%d %s %d\n", c, temp->name, temp->number);
temp->next = malloc(sizeof(struct node));
temp = temp->next;
temp->next = NULL;
c++;
}
So the last node will have data members with indeterminate values except the data member next
.
I am trying to answer your question how to write a bubble sort function for a singly-linked list.
To write a bubble sort function for a singly-linked list is not an easy task for such beginners as you and me. For example you need to write correctly a swap function for nodes of the list.
Here you are.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
char name[20];
int id;
struct node *next;
};
int push_back( struct node **head, const char *name, int id )
{
struct node *tmp = malloc( sizeof( struct node ) );
int success = tmp != NULL;
if ( success )
{
while ( *head != NULL ) head = &( *head )->next;
strcpy( tmp->name, name );
tmp->id = id;
tmp->next = NULL;
*head = tmp;
}
return success;
}
void display( struct node **head )
{
for ( struct node *current = *head; current != NULL; current = current->next )
{
printf( "{ %s, %d } ", current->name, current->id );
}
}
void swap( struct node **current )
{
struct node *tmp = ( *current )->next->next;
( *current )->next->next = *current;
*current = ( *current )->next;
( *current )->next->next = tmp;
}
void bubble_sort( struct node **head, int cmp( const void *, const void * ) )
{
if ( *head != NULL )
{
for ( struct node *last = NULL, *swapped = NULL; ( *head )->next != last; last = swapped )
{
swapped = ( *head )->next;
for ( struct node **first = head; ( *first )->next != last; first = &( *first )->next )
{
if ( cmp( ( *first )->next, *first ) < 0 )
{
swap( first );
swapped = ( *first )->next;
}
}
}
}
}
int cmp_id( const void *a, const void *b )
{
const struct node *left = a;
const struct node *right = b;
return ( right->id < left->id ) - ( left->id < right->id );
}
int cmp_name( const void *a, const void *b )
{
const struct node *left = a;
const struct node *right = b;
return strcmp( left->name, right->name );
}
int main(void)
{
struct node *head = NULL;
push_back( &head, "NameA", 25 );
push_back( &head, "NameB", 33 );
push_back( &head, "NameC", 23 );
push_back( &head, "NameD", 39 );
display( &head );
putchar( '\n' );
bubble_sort( &head, cmp_id );
display( &head );
putchar( '\n' );
bubble_sort( &head, cmp_name );
display( &head );
putchar( '\n' );
return 0;
}
The program output is
{ NameA, 25 } { NameB, 33 } { NameC, 23 } { NameD, 39 }
{ NameC, 23 } { NameA, 25 } { NameB, 33 } { NameD, 39 }
{ NameA, 25 } { NameB, 33 } { NameC, 23 } { NameD, 39 }
In the demonstrative program at first the list is sorted by IDs and then by names.
Thus all you need now is to build correctly the list from data in the used file.
回答3:
for bubble sorting a linked list,you first require a head pointer then two more pointers and the implementation will be same as that of bubble sort but with slight differences as linked list element can not be accessed by directly by a index you have to use the following two pointers for comparing values as you do for arrays in bubble sort.
pptr=head; //for the previou element
ptr=head->next;//for the next element
if(pptr->value > ptr->value) //comparing the value in linked list
don't forget to increment two pointers.
来源:https://stackoverflow.com/questions/47639448/bubble-sort-in-c-linked-list