简体   繁体   中英

How do I Bubble Sort a linked list?

I am trying to create a linked list and sort it by Bubble Sort. I succeeded to create the linked list, but when I am trying to Bubble Sort it, some accidents occur and I do not know the problem. What is the problem?

#include <stdio.h>
#include <stdlib.h>

//the struct of LinkedList
typedef struct Node
{
    int data;
    struct Node * pNext;
}NODE,*PNODE;

PNODE createList();//Creat one LinkedList
int lengthList(PNODE pHead);//get the length of LinkedList
void sortList(PNODE);//bubble sort

int main()
{
    int length;
    PNODE pHead=NULL;
    pHead=createList();
    sortList(pHead);
    return 0;
}
//Create LinkedList
PNODE createList()
{
    int i,n;
    int val;
    PNODE pHead=(PNODE)malloc(sizeof(NODE));
    if(pHead==NULL)
    {
        printf("failed to create!\n");
        exit(-1);
    }
    pHead->pNext=NULL;
    PNODE pTail=pHead;
    printf("please input the length of the LinkedList:");
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        printf("number %d is:\n",i+1);
        scanf("%d",&val);
        PNODE pNew=(PNODE)malloc(sizeof(NODE));
        if(pNew==NULL)
        {
            printf("failed to create\n");
            exit(-1);
        }
        pNew->data=val;
        pTail->pNext=pNew;
        pNew->pNext=NULL;
        pTail=pNew;
    }
    return pHead;
}
//get the length of LinkedList
int lengthList(PNODE pHead)
{
    int i=0;
    PNODE p=pHead->pNext;
    while(p!=NULL)
{
        i++;
        p=p->pNext;
    }
    return i;
}
//bubble sort
void sortList(PNODE pHead)
{
    int i,j,t,len;
    PNODE p,q;
    len=lengthList(pHead);
    p=pHead->pNext;
    for(i=0;i<len-1;i++)
    {
        for(j=0;j<len-i;j++)
        {
            q=p->pNext;
            if( p->data > q->data)
            {
                t=p->data;
                p->data=q->data;
                q->data=t;
            }
            p=q;//here may be the error
        }
    }
    return;
}

You are running off the end of your list in sortList

p=pHead->pNext;
for(i=0;i<len-1;i++)
{
    for(j=0;j<len-i;j++)
    {
        q=p->pNext;
        ....
        p=q;//here may be the error
    }
}

Bug 1) Your list is only len long but you are attempting to advance p to p->pNext far more then len times.

Bug 2) pHead does not need to be a full NODE - it's just a PNODE pointer. You never use its data field. You should have pHead point to the first node in the list, and then start your iteration at pHead rather than pHead->pNext.

Bug 3) You never clean up your memory allocations.

As @Airsource pointed out the bugs, keep in mind most of them are caused because of poor designing choice of your program. Try to do it like below & you will run into less errors

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct _Node{
    int data;
    struct _Node* next;
}Node;

typedef struct {
    Node* headPtr;
    Node* tailPtr;
    unsigned size;
}List;

static void create_node(List* list, int element) {
    if (list->headPtr == NULL) {
        // List is empty
        list->headPtr = (Node* )malloc(sizeof(Node));
        list->headPtr->data = element;
        list->headPtr->next = 0;
        list->tailPtr = list->headPtr;
        list->size++;
    }else{
        // List was already populated
        Node* temp = (Node* )malloc(sizeof(Node));
        temp->data = element;
        temp->next = 0;
        list->tailPtr->next = temp;
        list->tailPtr = temp;
        list->size++;
    }
}

void create_list(List* list, int length){
    int ele;
    int i;
    list->headPtr = list->tailPtr = 0;
    list->size = 0;

    for (i = 0; i < length; i++) {
        scanf("%d", &ele);
        create_node(list, ele);
    }
}

void print_list(List* list){
    Node* loop = list->headPtr;
    while(loop){
        printf("%d ", loop->data);
        loop = loop->next;
    }
    printf("\n");
}


 int main(){
    List* list;
    int n;
    printf("Enter the length of the list: ");
    scanf("%d", &n);
    create_list(list, n);
    print_list(list);
    bubble_sort(list);
    print_list(list);
    if (cleanup(list))
        printf("Memory rescued!!\n");
    else
        printf("OOPS!! Error\n");
 return 0;
}

Moreover, you can get the size anytime just by list->size . No need for separate function to do that.

Finally to sort it using bubble sort you could do something like this below

void bubble_sort(List* list) {
    int i, j;
    Node* first, *second;
    int temp;
    first = list->headPtr;
    second = list->headPtr->next;
    for (i = 0; i < list->size - 1; i++) {
        for (j = 0; j < list->size - i - 1; j++) {
            if (first->data > second->data){
                temp = first->data;
                first->data = second->data;
                second->data = temp;
            }
            first = second;
            second = second->next;
        }
        first = list->headPtr;
        second = list->headPtr->next;
    }
}

and for cleanup you do this

bool cleanup(List* list) {
    Node* curr = list->headPtr;
    Node* nxt = list->headPtr->next;
    while(nxt){
        free(curr);
        curr = nxt;
        nxt = curr->next;
    }
    list->headPtr = list->tailPtr = 0;
    list->size = 0;
    return !nxt ? true: false;
}

There are couple of bugs in your program. I will address them one by one:

  1. Line 28 PNODE pHead=(PNODE)malloc(sizeof(NODE)); Here you are allocating a memory and creating a node before checking if n>0 or not.

  2. Line 36 printf("please input the length of the LinkedList:");
    Now up to this point you have created a one node, head node which has no value in it (so contains garbage)

In effect your createList() creates a linked list with n+1 nodes instead of n and the head->value contains garbage.

Solution:

printf("please input the length of the LinkedList:");
scanf("%d", &n);
for(i=0; i<n; i++)
{
    PNODE pNew = (PNODE)malloc(sizeof(NODE));

    if(pNew == NULL)
    {
        printf("failed to create!\n");
        exit(-1);
    }

    scanf("%d", &val);
    pNew->data = val;
    pNew->pNext = NULL;

    if (!i)
        pHead = pNew;
    else
        pTail->pNext = pNew;
    pTail = pNew;      
}

return pHead;
  1. Line 59 PNODE p=pHead->pNext;
    Here you are counting nodes starting from the second node (leaving out head ). No wonder you will get length as n as you have created a linked list of length n+1 in your createList()

Imagine what if n = 0 and thus pHead = NULL ?
Then this line will result in SegFault .

Solution:
change PNODE p=pHead->pNext; to PNODE p = pHead;

  1. Line 73 p=pHead->pNext;
    Here you will start sorting excluding the first node, head node.
    Also this should be inside the outter for and outside of the inner for to reset the p to first node for each pass.

  2. Line 76 for(j=0;j<len-i;j++)
    Here j must be less than len - 1 - i as in pass 1 ( i = 0 ) in the worst case j will be equal to len-1 for j < len-i , where p will point to the last node of linked list and q will be NULL as q = p -> pNext . Which will make q->data to result in SegFault .

To summarise, your sort routine is producing SegFault in the very first Pass and even if it didn't (by properly adjusting the loop-terminating expression in inner for ) the outer for loop is contributing nothing towards the sorting except increasing the time complexity.

Solution:

for(i = 0; i < len - 1; i++)
{
    p = pHead;
    for(j = 0; j < len - 1 - i; j++)
    {
        q = p -> pNext;
        if(p->data > q->data)
        {
            t = p -> data;
            p -> data = q -> data;
            q -> data = t;
        }
        p = q;
    }
}

A question:
How are you checking whether element have been sorted or not?
A printList() routine would have been helpful in spotting the above bugs.

"Always verify whether you correctly stored the input or not by explicitly printing the same before processing it!"

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