C - Problem Bubble sorting linked list

Hello,

I'm having problems sorting a linked list alphabetically. The link list is being correctly populated but it seems that the bubblesort() function is implemented incorrectly. When I read the following textfile:
apple tree house.
the output after bubblesort() is:
apple --> house --> tree --> NULL
No problems there. But when I try the following text:
house dog tree friend.
the output is:
house --> tree --> NULL

After trying dozens of different wordcombinations I can't seem to find a pattern in why it would sort incorrectly. Again the linked list is printed correctly before sorting.

The main function and 'd' is left out as it's not used in bubblesort().

Any thoughts?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Linkedlist.h"
#include "prototypes.h"

struct Nodes {
   char *data;
   struct Nodes *nextPtr; /* pointer to next structure */
};

typedef struct Nodes NODES;
typedef NODES *NODESPTR;

void insert(NODESPTR *, char *);
void printList(NODESPTR);
NODESPTR bubblesort(NODESPTR);
int isChar(char);
void linkedList();

void linkedList(){

    d.count = 0;
    NODESPTR startPtr = NULL;

    d.c = fgetc(d.fileDocument);
    printf("processing file...\n\n");

    while ((d.d = fgetc(d.fileDocument)) != EOF) {

          /*If two lines in a row*/
          if ((d.c == '\n') && (d.d == '\n')) {
			}

          /* if not two non-characters in a row */
		  else if ((isChar(d.c) == 0) && (isChar(d.d) == 0)) {
		       d.c = d.d;
		  }

          /* if c and d are both characters */
		  else if ((isChar(d.c) == 1) && (isChar(d.d) == 1)) {
		      d.word[d.count] = tolower(d.c);
			  d.c = d.d;
			  d.count++;
          }

            /* if c is character and d is space, return, tab, or new line */
          else if ((isChar(d.c) == 1) && (isChar(d.d) == 0)) {
		      d.word[d.count] = d.c;
		      d.word[++d.count] = '\0';

			  char *newword = malloc(strlen(d.word)+1);
			  strcpy(newword, d.word);
			  insert(&startPtr, newword);

			  d.c = d.d;
			  d.count = 0;
          }

          /* if d is start of new word */
		  else if ((isChar(d.d) == 1) && (isChar(d.c) == 0)) {
		      d.c = d.d;
          }
    }
  fclose(d.fileDocument);
  printList(startPtr);
  bubblesort(startPtr);
  printList(startPtr);

}

void insert(NODESPTR *sPtr, char *value)
{
   NODESPTR newPtr, previousPtr, currentPtr;

   newPtr = malloc(sizeof(NODES));


   if (newPtr != NULL) {    /* is space available */
   	  newPtr->data = malloc(sizeof(value));
   	  newPtr->data = value;
      newPtr->nextPtr = NULL;

      previousPtr = NULL;
      currentPtr = *sPtr;

      while (currentPtr != NULL && value > currentPtr->data) {
         previousPtr = currentPtr;
         currentPtr = currentPtr->nextPtr;  /* walk to next node */
      }

      if (previousPtr == NULL) {    /* if the list is empty, create the first node */
         newPtr->nextPtr = *sPtr;
         *sPtr = newPtr;
      }
      else {
         previousPtr->nextPtr = newPtr;
         newPtr->nextPtr = currentPtr;
      }
   }
   else
      printf("%s not inserted. No memory available.\n", value);
}

NODESPTR bubblesort(NODESPTR list)
{
    NODESPTR lst, tmp = list, prev, potentialprev = list;
    int idx, idx2, n = 0;

    /*nr of nodes*/
    for (;tmp->nextPtr; tmp=tmp->nextPtr)
    {
        n++;
    }

    for (idx=0; idx<n-1; idx++)
    {
        for (idx2=0,lst=list; lst && lst->nextPtr && (idx2<=n-1-idx); idx2++)
        {
            if (!idx2)
            {
                /*at beginning, treat start
                node as prev node*/
                prev = lst;
            }

            /*compare two nodes*/
            if ( strcmp ( lst->data, lst->nextPtr->data ) == 1 )
            {
                /*swap nodes*/
                tmp = (lst->nextPtr?lst->nextPtr->nextPtr:0);

                if (!idx2 && (prev == list))
                {
                    /*do not have any special sentinal nodes
                    so change beginning of the list to point
                    to the smallest swapped node*/
                    list = lst->nextPtr;
                }
                potentialprev = lst->nextPtr;
                prev->nextPtr = lst->nextPtr;
                lst->nextPtr->nextPtr = lst;
                lst->nextPtr = tmp;
                prev = potentialprev;
            }
            else
            {
                lst = lst->nextPtr;
                if(idx2)
                {
                    /*just keep track of previous node, for swapping nodes this is required*/
                    prev = prev->nextPtr;
                }
            }
        }
    }
    return list;
}

/* Print the list */
void printList(NODESPTR currentPtr)
{
   if (currentPtr == NULL)
      printf("List is empty.\n\n");
   else {
      printf("The list is:\n");

      while (currentPtr != NULL) {
         printf("%s --> ", currentPtr->data);
         currentPtr = currentPtr->nextPtr;
      }

      printf("NULL\n\n");
   }
}
Last edited on
ok... found the pattern. It seems that the first two chars of the first word are set as some kind of limit. If one of the following words begins with two chars =< then the first two chars of the first word the output gets scrambled. Example:
appel tree pie
works out fine:
appel --> pie --> tree --> NULL
But with this:
appel aapel tree pie.
I get:
appel --> pie --> tree --> NULL
If corrected:
appel aqpel tree pie. (Notice the 'q' in 'aqpel' is higher than the 'ap' in 'appel')
It's ok again:
appel --> aqpel --> pie --> tree --> NULL

My brains hurt -_-
Still can't fix it though... does anyone have an idea on how to solve this?
First of all: to me your function looks overly complicated and has some redundant variables. A more simplistic approach along the lines of:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* Quick'n dirty pseudo code */
bubblesort()
{
  while(swapped) {
    swapped = false;
    for(list; list != end; list++) {
      if(firstIsLower) {
        swap;
        swapped = true;
      }
    }
  }
}

would do IMO.

That beeing said your problem seems to be that you are not updating startPtr with the returnvalue of bubblesort(). Your just printing the initial list root.

- Andreas
Aw crap, I feel like a retard... Thx man you helped me out big time. I'll take a look at simplifying the function, it will be good practice because I still suck at linked lists.
Topic archived. No new replies allowed.