Avatar billede phbecker Nybegynder
14. marts 2005 - 22:09 Der er 10 kommentarer og
1 løsning

Sortering af doubly linked list?

Hejsa,

Stærkt hjulpet på vej af dette indlæg: http://eksperten.dk/spm/417877 og de dertil hørende svar har jeg fået lavet mig en funktion til at sortere min linked list efter karakterer (som eksempel i dette tilfælde), men når jeg kører den bliver karaktererne faktisk ikke sorteret, og jeg kan ikke lige umiddelbart se hvorfor...

Min grundlæggende struct ser således ud:

struct node // Doubly linked list
{
    char* name;
    int grade;
    struct node* next;
    struct node* previous;
};

Og min funktion til at sortere dem med ser sådan ud:

void sortgrades(struct node *node)
{
    //header contains the first element from the original linked list
    //remainder is the rest of the linked list
   
    struct node *header=NULL, *remainder, *first=NULL, *parent=NULL;
    int i = 1;

    printf("Ordering list...\n");

    // Here we split list in two, header and remainder as defined above:
    while(node) // As long as we are dealing with a non-NULL element, aka we're in our linked list
    {
        if (i == 1) // First iteration, so we need to assign the header
        {
            header = (struct node *)malloc(sizeof(struct node));
            header->name = node->name;
            header->grade = node->grade;
            header->next = NULL;
        }
        else
        {
            remainder = (struct node *)malloc(sizeof(struct node)); // Must allocate memory for it!
            if (i == 2) // Second iteration (special case)
                first = remainder;

            remainder->name = node->name;
            remainder->grade = node->grade;
            remainder->next = NULL;

            if(parent)
                parent->next = remainder;

            parent = remainder;
        }
        node = node->next;
        i++;
    }
}

Spørgsmålet er så, hvordan jeg kan få det til at virke - sig endelig til, hvis I gerne vil se al koden osv.! :-) Og hvilken indflydelse har det, at min linked list er doubly linked frem for ovenstående link's singly linked natur? Ydermere er jeg ikke helt sikker på, hvad parent egentlig er i denne funktion - mit bud er, at den svarer til hvad der ville være node->previous i min doubly linked list. På forhånd mange tak!
Avatar billede bertelbrander Novice
14. marts 2005 - 22:42 #1
Jeg forstår ikke rigtigt algoritmen, så vidt jeg kan se sker der bare en kopiering.

Der er en implementation af en dobbelt linket liste her, den har også en sort:
http://home20.inet.tele.dk/midgaard/snip/linklist.html
Avatar billede arne_v Ekspert
14. marts 2005 - 23:37 #2
En modificeret udgave af noget kode jeg havde liggende:

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

struct node
{
  char *name;
  int val;
  struct node *next;
  struct node *prev;
};

struct node *first2last(struct node *first)
{
    struct node *last;
    last = first;
    if(last!=NULL) while(last->next!=NULL) last=last->next;
    return last;
}

void add(struct node **first, char *name, int val)
{
    struct node *extra,*last;
    extra = (struct node *)malloc(sizeof(struct node));
    extra->name = name;
    extra->val = val;
    extra->next = NULL;
    if(*first==NULL)
    {
        *first = extra;
        extra->prev = NULL;
    }
    else
    {
        last = *first;
        while(last->next!=NULL) last=last->next;
        last->next = extra;
        extra->prev = last;
    }
}

void print(struct node *first)
{
    struct node *curr;
    printf("----------------\n");
    curr = first;
    while(curr!=NULL)
    {
        printf("%s %d\n",curr->name,curr->val);
        curr = curr->next;
    }
    printf("----------------\n");
}

void print2(struct node *last)
{
    struct node *curr;
    printf("----------------\n");
    curr = last;
    while(curr!=NULL)
    {
        printf("%s %d\n",curr->name,curr->val);
        curr = curr->prev;
    }
    printf("----------------\n");
}

void sort(struct node **first)
{
    struct node *p1,*p2,*pp1,*pp2,*temp;
    p1 = *first;
    pp1 = NULL;
    while(p1!=NULL)
    {
        pp2 = p1;
        p2 = p1->next;
        while(p2!=NULL)
        {
            if(p2->val < p1->val)
            {
                /* swap pointers */
                temp = p2;
                p2 = p1;
                p1 = temp;
                /* update next and prev pointers */
                if(p2->next!=p1)
                {
                    temp = p2->next;
                    p2->next = p1->next;
                    if(p1->next!=NULL)
                    {
                        p1->next->prev = p2;
                    }
                    p1->next = temp;
                    if(temp!=NULL)
                    {
                        temp->prev = p1;
                    }
                    pp2->next = p2;
                    p2->prev = pp2;
                }
                else
                {
                    p2->next = p1->next;
                    if(p1->next!=NULL)
                    {
                        p1->next->prev = p2;
                    }
                    p1->next = p2;
                    p2->prev = p1;
                }
                if(pp1==NULL)
                {
                    *first = p1;
                    p1->prev = NULL;
                }
                else
                {
                    pp1->next = p1;
                    p1->prev = pp1;
                }
            }
            pp2 = p2;
            p2 = p2->next;
        }
        pp1 = p1;
        p1 = p1->next;
    }
}

int main()
{
  struct node *first = NULL;
  add(&first, "a", 111);
  add(&first, "bb", 22);
  add(&first, "ccc", 3);
  printf("usorteret:\n");
  print(first);
  printf("usorteret (omvendt):\n");
  print2(first2last(first));
  sort(&first);
  printf("sorteret:\n");
  print(first);
  printf("sorteret (omvendt):\n");
  print2(first2last(first));
  add(&first, "d", 4);
  add(&first, "e", 5);
  printf("usorteret:\n");
  print(first);
  printf("usorteret (omvendt):\n");
  print2(first2last(first));
  sort(&first);
  printf("sorteret:\n");
  print(first);
  printf("sorteret (omvendt):\n");
  print2(first2last(first));
  return 0;
}
Avatar billede phbecker Nybegynder
15. marts 2005 - 18:52 #3
Mange tak for kodeeksemplet Arne! Jeg har siddet og tilpasset det min kode en smule men er stadig ikke helt sikker på, hvordan det virker. Måske du havde lidt forklarende ord at give med? :-) Jeg er endvidere stødt på det problem, at den ikke giver mig hele listen efter at have sorteret. Først den "oprindelige" linked list hvis start-node jeg giver som argument: (udskrevet med min dertil indrettede funktion)

Name: Student 1, grade: 7
Name: Student 2, grade: 10
Name: Student 3, grade: 3
Name: Student 4, grade: 6
Name: Student 5, grade: 11
Name: Student 6, grade: 8
Name: Student 7, grade: 9
Name: Student 8, grade: 13
Name: Student 9, grade: 11
Name: Student 10, grade: 10
Name: Appended student, grade: 13

Efter sortering printes følgende liste:

Name: Student 1, grade: 7
Name: Student 6, grade: 8
Name: Student 7, grade: 9
Name: Student 2, grade: 10
Name: Student 10, grade: 10
Name: Student 9, grade: 11
Name: Student 5, grade: 11
Name: Student 8, grade: 13
Name: Appended student, grade: 13

Dette er naturligvis korrekt sorteret, egentlig, men hvor er resten af elementerne blevet af? Det kan jeg ikke lige umiddelbart se...

Min tilpassede kode til funktionen ser således ud:

void sort(struct node *first)
{
    struct node *p1,*p2,*pp1,*pp2,*temp;
    p1 = first;
    pp1 = NULL;
    while(p1)
    {
        pp2 = p1;
        p2 = p1->next;
        while(p2)
        {
            if(p2->grade < p1->grade)
            {
                // swap pointers
                temp = p2;
                p2 = p1;
                p1 = temp;
                // update next and prev pointers
                if(p2->next!=p1)
                {
                    temp = p2->next;
                    p2->next = p1->next;
                    if(p1->next)
                    {
                        p1->next->previous = p2;
                    }
                    p1->next = temp;
                    if(temp)
                    {
                        temp->previous = p1;
                    }
                    pp2->next = p2;
                    p2->previous = pp2;
                }
                else
                {
                    p2->next = p1->next;
                    if(p1->next)
                    {
                        p1->next->previous = p2;
                    }
                    p1->next = p2;
                    p2->previous = p1;
                }
                if(pp1==NULL)
                {
                    first = p1;
                    p1->previous = NULL;
                }
                else
                {
                    pp1->next = p1;
                    p1->previous = pp1;
                }
            }
            pp2 = p2;
            p2 = p2->next;
        }
        pp1 = p1;
        p1 = p1->next;
    }
}

For god ordens skyld er her min funktion til at udskrive:

void printgrades(struct node *node) // Prints the name and grade of each node element
{
    while(node)
    {
        printf("Name: %s, grade: %i\n", node->name, node->grade);
        node = node->next;
    }
}

På forhånd tak :-)
Avatar billede arne_v Ekspert
15. marts 2005 - 23:46 #4
mystisk

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

struct node
{
  char *name;
  int val;
  struct node *next;
  struct node *prev;
};

void add(struct node **first, char *name, int val)
{
    struct node *extra,*last;
    extra = (struct node *)malloc(sizeof(struct node));
    extra->name = name;
    extra->val = val;
    extra->next = NULL;
    if(*first==NULL)
    {
        *first = extra;
        extra->prev = NULL;
    }
    else
    {
        last = *first;
        while(last->next!=NULL) last=last->next;
        last->next = extra;
        extra->prev = last;
    }
}

void print(struct node *first)
{
    struct node *curr;
    printf("----------------\n");
    curr = first;
    while(curr!=NULL)
    {
        printf("Name: %s, grade: %d\n",curr->name,curr->val);
        curr = curr->next;
    }
    printf("----------------\n");
}

void sort(struct node **first)
{
    struct node *p1,*p2,*pp1,*pp2,*temp;
    p1 = *first;
    pp1 = NULL;
    while(p1!=NULL)
    {
        pp2 = p1;
        p2 = p1->next;
        while(p2!=NULL)
        {
            if(p2->val < p1->val)
            {
                /* swap pointers */
                temp = p2;
                p2 = p1;
                p1 = temp;
                /* update next and prev pointers */
                if(p2->next!=p1)
                {
                    temp = p2->next;
                    p2->next = p1->next;
                    if(p1->next!=NULL)
                    {
                        p1->next->prev = p2;
                    }
                    p1->next = temp;
                    if(temp!=NULL)
                    {
                        temp->prev = p1;
                    }
                    pp2->next = p2;
                    p2->prev = pp2;
                }
                else
                {
                    p2->next = p1->next;
                    if(p1->next!=NULL)
                    {
                        p1->next->prev = p2;
                    }
                    p1->next = p2;
                    p2->prev = p1;
                }
                if(pp1==NULL)
                {
                    *first = p1;
                    p1->prev = NULL;
                }
                else
                {
                    pp1->next = p1;
                    p1->prev = pp1;
                }
            }
            pp2 = p2;
            p2 = p2->next;
        }
        pp1 = p1;
        p1 = p1->next;
    }
}

int main()
{
  struct node *first = NULL;
  add(&first, "Student 1", 7);
  add(&first, "Student 2", 10);
  add(&first, "Student 3", 3);
  add(&first, "Student 4", 6);
  add(&first, "Student 5", 11);
  add(&first, "Student 6", 8);
  add(&first, "Student 7", 9);
  add(&first, "Student 8", 13);
  add(&first, "Student 9", 11);
  add(&first, "Student 10", 10);
  add(&first, "Appended student", 13);
  printf("usorteret:\n");
  print(first);
  sort(&first);
  printf("sorteret:\n");
  print(first);
  return 0;
}

giver

usorteret:
----------------
Name: Student 1, grade: 7
Name: Student 2, grade: 10
Name: Student 3, grade: 3
Name: Student 4, grade: 6
Name: Student 5, grade: 11
Name: Student 6, grade: 8
Name: Student 7, grade: 9
Name: Student 8, grade: 13
Name: Student 9, grade: 11
Name: Student 10, grade: 10
Name: Appended student, grade: 13
----------------
sorteret:
----------------
Name: Student 3, grade: 3
Name: Student 4, grade: 6
Name: Student 1, grade: 7
Name: Student 6, grade: 8
Name: Student 7, grade: 9
Name: Student 2, grade: 10
Name: Student 10, grade: 10
Name: Student 9, grade: 11
Name: Student 5, grade: 11
Name: Student 8, grade: 13
Name: Appended student, grade: 13
Avatar billede arne_v Ekspert
15. marts 2005 - 23:55 #5
Hov !!

Du har rettet

void sort(struct node **first)

til

void sort(struct node *first)

så får du ikke ændret first og derfor bliver alle mindre end den gamle
first væk !!
Avatar billede arne_v Ekspert
15. marts 2005 - 23:58 #6
Grundliggende er sorteringen den samme somm i dette simple array sortering:

#include <stdio.h>
#include <string.h>

struct data
{         
    char navn[20];
    char sort[20];
    char farve[20];
    int pris;
};

int main()
{
    int i,j;
    struct data a[3],tmp;
    /* initialiser data */
    strcpy(a[0].navn,"ccc");
    a[0].pris = 100;
    strcpy(a[1].navn,"bb");
    a[1].pris = 10;
    strcpy(a[2].navn,"a");
    a[2].pris = 1;
    /* udskriv data */
    for(i=0;i<3;i++)
    {
      printf("%s %d\n",a[i].navn,a[i].pris);
    }
    /* sorter */
    for(i=0;i<3;i++)
    {
        for(j=(i+1);j<3;j++)
        {
            if(strcmp(a[i].navn,a[j].navn)>0)
            {
                tmp = a[i];
                a[i] = a[j];
                a[j] = tmp;
            }
        }
    }
    /* udskriv data */
    for(i=0;i<3;i++)
    {
      printf("%s %d\n",a[i].navn,a[i].pris);
    }
    return 0;
}
Avatar billede phbecker Nybegynder
16. marts 2005 - 00:08 #7
Tak, nu har jeg rettet det tilbage til at bruge en dobbeltpointer igen, dum fejl at begå... Anyways, det ændrer desværre ikke på udfaldet - jeg får præcis det samme output og sorterede liste som beskrevet før, efter at have rettet tilbage til
void sort(struct node **first)...
Avatar billede phbecker Nybegynder
16. marts 2005 - 00:11 #8
...Måske har det noget at gøre med, at det, jeg kalder sort-funktionen med, ikke er en pointer, men blot en struct? Altså:

struct node start;
// Kode imellem
start.next = NULL;
start.previous = NULL;
node = &start; // Starten på linked list er her

...Hvorefter jeg siden kalder sort med &start
Avatar billede arne_v Ekspert
16. marts 2005 - 07:07 #9
Ja det duer ikke.

Du skal kalde med adressen på en pointer til struct.

Fordi den første ændrer sig jo ved soteringen.
Avatar billede phbecker Nybegynder
16. marts 2005 - 14:37 #10
Mange tak for hjælpen Arne! Smider du lige et svar så jeg kan give dit point? :)
Avatar billede arne_v Ekspert
16. marts 2005 - 17:01 #11
kommer her
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester