J
Joe Estock
I'm attempting to sort a doubly linked list at the time that an item is
added. When I add the items in increasing order everything works
correctly, however when I add them in reverse order the correlation is
messed up. The list, however, is sorted except for element 0 (or
whatever value was the first to be added). I've been working on this
most of the night so maybe I am overlooking something. Any help would be
much appreciated. Below is a minimal example that can be compiled (sorry
for the length of the code, however I couldn't make it any smaller).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum { false, true };
typedef int bool;
struct dll_t
{
int val;
struct dll_t *next;
struct dll_t *prev;
};
#define compare(x, y) memcmp(x, y, sizeof(x))
#define icompare(x, y) ((x) - (y))
bool add_node_value(struct dll_t **dll, int val);
int main(void)
{
struct dll_t *dll;
struct dll_t *p;
int i;
dll = NULL;
/* this works perfectly */
/*for(i = 0; i < 10; i++)
add_node_value(&dll, i);*/
/* this does not */
for(i = 9; i > -1; i--)
add_node_value(&dll, i);
printf("walking\n");
for(p = dll; p; p = p->next)
{
printf("%d (p: %d n: %d)\n", p->val,
p->prev == NULL ? -1 : p->prev->val,
p->next == NULL ? -1 : p->next->val);
}
return(0);
}
bool add_node_value(struct dll_t **dll, int val)
{
struct dll_t *tmp;
struct dll_t *p;
tmp = malloc(sizeof(*tmp));
tmp->next = NULL;
tmp->val = val;
if(*dll == NULL)
{
tmp->prev = NULL;
*dll = tmp;
return(true);
}
p = *dll;
printf("icompare(%d, %d) = %d\n",
val, p->val, icompare(val, p->val));
if(icompare(tmp->val, p->val) > 0)
{
/* tmp->val is larger - insert tmp after p */
for(p = *dll; (val > p->val) && p != NULL; p = p->next)
{
if(p->next == NULL)
break;
}
tmp->prev = p;
tmp->next = p->next;
p->next = tmp;
printf("p->prev: %d p->val: %d p->next: %d\n",
p->prev == NULL ? -1 : p->prev->val, p->val,
p->next == NULL ? -1 : p->next->val);
}
else
{
/* tmp->val is smaller - insert p before tmp */
for(p = *dll; (tmp->val < p->val) && p != NULL; p = p->next)
{
if(p->next == NULL)
break;
}
/* this is where the problem is */
tmp->prev = (*dll);
tmp->next = (*dll)->next;
(*dll)->next = tmp;
printf("p->prev: %d p->val: %d p->next: %d\n",
p->prev == NULL ? -1 : p->prev->val, p->val,
p->next == NULL ? -1 : p->next->val);
}
return(true);
}
added. When I add the items in increasing order everything works
correctly, however when I add them in reverse order the correlation is
messed up. The list, however, is sorted except for element 0 (or
whatever value was the first to be added). I've been working on this
most of the night so maybe I am overlooking something. Any help would be
much appreciated. Below is a minimal example that can be compiled (sorry
for the length of the code, however I couldn't make it any smaller).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum { false, true };
typedef int bool;
struct dll_t
{
int val;
struct dll_t *next;
struct dll_t *prev;
};
#define compare(x, y) memcmp(x, y, sizeof(x))
#define icompare(x, y) ((x) - (y))
bool add_node_value(struct dll_t **dll, int val);
int main(void)
{
struct dll_t *dll;
struct dll_t *p;
int i;
dll = NULL;
/* this works perfectly */
/*for(i = 0; i < 10; i++)
add_node_value(&dll, i);*/
/* this does not */
for(i = 9; i > -1; i--)
add_node_value(&dll, i);
printf("walking\n");
for(p = dll; p; p = p->next)
{
printf("%d (p: %d n: %d)\n", p->val,
p->prev == NULL ? -1 : p->prev->val,
p->next == NULL ? -1 : p->next->val);
}
return(0);
}
bool add_node_value(struct dll_t **dll, int val)
{
struct dll_t *tmp;
struct dll_t *p;
tmp = malloc(sizeof(*tmp));
tmp->next = NULL;
tmp->val = val;
if(*dll == NULL)
{
tmp->prev = NULL;
*dll = tmp;
return(true);
}
p = *dll;
printf("icompare(%d, %d) = %d\n",
val, p->val, icompare(val, p->val));
if(icompare(tmp->val, p->val) > 0)
{
/* tmp->val is larger - insert tmp after p */
for(p = *dll; (val > p->val) && p != NULL; p = p->next)
{
if(p->next == NULL)
break;
}
tmp->prev = p;
tmp->next = p->next;
p->next = tmp;
printf("p->prev: %d p->val: %d p->next: %d\n",
p->prev == NULL ? -1 : p->prev->val, p->val,
p->next == NULL ? -1 : p->next->val);
}
else
{
/* tmp->val is smaller - insert p before tmp */
for(p = *dll; (tmp->val < p->val) && p != NULL; p = p->next)
{
if(p->next == NULL)
break;
}
/* this is where the problem is */
tmp->prev = (*dll);
tmp->next = (*dll)->next;
(*dll)->next = tmp;
printf("p->prev: %d p->val: %d p->next: %d\n",
p->prev == NULL ? -1 : p->prev->val, p->val,
p->next == NULL ? -1 : p->next->val);
}
return(true);
}