简体   繁体   中英

Infinite loop while sorting a linked list in C

I am new to C programming, and I have to sort my linked list. This linked list represents a polynomial which has been created by user's input. Each node has a coefficient and a power. When I try to sort the list and return it to the main function where I print it, nothing is printed (I think my program never exits a while loop).

Here I create the struct:

struct node
{
    int sunt;
    int dun;
    struct node* next;
};
typedef struct node* Poly;

Here is my code where I sort the list ( head is my initial list's name):

struct node* poly = head;

struct node* temp;
int length = 0;

while (poly != NULL)
{
    length++;
    poly = poly->next;
}

poly = head;

while (length > 0)
{
    int i = 0;
    while ((poly != NULL) && (poly->next != NULL))
    {
        if (poly->dun > poly->next->dun)
        {
            temp = poly;
            poly = poly->next;
            poly->next = temp;
            if(i = 0)
            {
                head = poly;
            }
            i ++;
        }
        else
        {
            if(i = 0)
            {
                head = poly;
            }
            i ++;
        }
        poly = poly->next;
    }
    length --;
    poly = head;
}
return head;

And here is where I print the list in main function (POLYmake function is where I create and sort the list):

poly1 = POLYmake();

while(poly1 != NULL)
{
    printf("%d %d \n", poly1->sunt, poly1->dun);
    poly1 = poly1->next;
}

I know it's quite complicated, but I have no experience in C and I hope you could help me.

This loop

while(length > 0)

Will always be true, because when you finish going through your list, you only decrement it by one.

In addition, the following code:

if(i = 0)
{
    head = poly;
}

Should be

if(i == 0)
{
    head = poly;
}

Firstly...

if(i=0)

is wrong as it sets i

There's more though I think... you're setting the next nodes -> next to be the current one and vice versa, BUT, you're not setting the previous node's -> next OR the next node's->next as well, so you could well be creating a loop ie both of the next contain the same pointer. You need to tie up all the links in the list to do this and it's a pain!

so it should be:

node* prev = null

[...] ensure you set the prev after each iteration

then
node* swap1 = poly;
node* swap2 = poly->next;

swap1->next = swap2->next; (which you'd have to null check for beforehand)
swap2->next = swap1;
prev->next = swap2;

BUT: Conceptually, you're swapping entire links around just to swap some numbers. You could embed a struct pointer (which contain the ACTUAL values you're interested in) within the linkedlist entries and then swap those around rather than dynamically restructuring your list itself.

The moral of the story is, a linkedlist isn't the best structure for a bubble sort.

I think you break your linked list and form a loop in the inner loop's first if branch

temp = poly; // (1) 
poly = poly->next; // (2)
poly->next = temp; // (3)

Assume you have a list a -> b -> c -> ... and enter the if then poly points to a so will temp after (1). After (2) poly will point to b. The (3) statement will then assign the next pointer of b to temp, which is a. This results in a cycle a -> b -> a -> b -> ... and you never reach c and therefore stay in the loop forever. You should set the next pointer of a to c if you swap a and b.

Edit: In addition the previous node (whose next pointer points to poly) has to be updated as well. To do so, the previous node can be kept in a separate prev pointer and prev->next can be set to that node that is first of the two after the swap.

Let's focus on this

temp = poly;
poly = poly->next;
poly->next = temp;

Presumably the idea is to swap two elements in the list. So let's look at a list

item1 -> item2 -> item3 -> item4 -> NULL

Assume poly points at item2 and you need to swap it with item3. The first thing you do is set temp to poly, so both temp and poly point to item2.

item1 -> item2 -> item3 -> item4 -> NULL
         poly
         temp

Then you move poly to point at poly->next which is item3

item1 -> item2 -> item3 -> item4 -> NULL
                  poly
         temp

Then you set poly's next pointer to point at temp which is item2

             V------------
item1 -> item2 -> item3 -|  item4 -> NULL
                  poly
         temp

Note that now nothing points at item4. It's a memory leak. Note also that your list ends in a loop which means you'll never come across NULL and you'll never exit the inner loop.


How to solve this?

You'll notice that the item before poly is going to need to change its next pointer too, so you'll be needing a previous pointer. This is how i would do it

// Set up the loop before you start
struct node* previous = NULL;
poly = head;
while (poly != NULL && poly->next != NULL)
{
    if (poly->dun > poly->next->dun)
    {
        if (previous == NULL)
        {
            head = poly->next;
        }
        else
        {
            previous->next = poly->next;
        }
        struct node* tail = poly->next->next;
        poly->next->next = poly;
        poly->next = tail;
    }
    previous = poly;
    poly = poly->next;
}

I think that'll work. Haven't tested it.

It is shown with the actual code a simple algorithm.

typedef struct node Node;
Node *bubbleSort(Node *head){
    if(head == NULL || head->next == NULL)//no need sort
        return head;

    Node anchor = { 0, 0, head }, *sentinel = NULL;
    while(1){
        Node *prev = &anchor, *curr = prev->next, *next = curr->next;
        if(next == sentinel)
            break;
        while(next != sentinel){
            Node *rest = next->next;
        //  prev --> curr --> next --> rest
            if(curr->dun > next->dun){
                prev->next = next;
                next->next = curr;
                curr->next = rest;

                prev = next;
                //curr = curr;
                next = curr->next;
            } else {
                prev = curr;
                curr = curr->next;
                next = curr->next;
            }
        }
        sentinel = curr;
    }

    return anchor.next;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM