Avatar billede tchami Nybegynder
25. oktober 2003 - 21:03 Der er 12 kommentarer og
1 løsning

C: Indsætte element på n-te plads i linked list

Hej,

Jeg skal have sorteret en linket liste efter karakter, startende med den laveste.

Det er jeg også næsten færdig med, men den virker ikke helt.

funktionen gradelist opretter min linkede liste.

funktionen orderlist splitter min linkede liste op i to nye lister, en med det første element fra den originale liste (head) og en med de resterende (remaining).

funktionen sortlist sorterer de to nye lister ved at itere igennem remaining-listen og sammenligne det element vi står på i remaining med head-listen og hvis det er mindre så indsætte det før head-elementet.
Det virker også fint nok, men hvis remaining-elementet nu er større, er jeg nødt til at iterere igennem head-listen for at være sikker på at remaining-elementet ikke er mindre end andre elementer i head-listen. Det gør jeg sådan (current peger på det første element i head):

    while(current != NULL){

        if (remaining->grade <= current->grade){
            parent = current;
            printf("Indsaet her!%d <= %d", remaining->grade, current->grade);
            temp = (Node*)malloc(sizeof(Node));
            temp->name = remaining->name;
            temp->grade = remaining->grade;
            temp->next = parent;
            head->next = temp;
            break;
        }

        current = current->next;
    }
   
Hvis remaining-elementet er mindre eller lig head-elemtentet vi står på, skal det indsættes før dette, men det kan jeg simpelthen ikke få til at virke ordentligt.

Kan nogen guide mig på rette vej?

Koden står herunder:

struct node{
    char* name;
    int grade;
    struct node* next;
};

typedef struct node Node;


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

Node *makestartlist();
void gradelist(Node* node);
void orderlist(Node* node);
void sortlist(Node* remaining, Node* head);
int get_high(Node* node);
int listlenghth(Node* node);

main(){

    int choice, count;
    char quit;
    Node* nodelist;

    //Make default linked list
    nodelist = makestartlist();

    do{

        // User-interface
        printf("*********MENU**********\n");
        printf("3. Order list in increasing order\n");
        printf("7. Stop\n");

        scanf("%d", &choice);

        switch (choice) {

        case 3 :
                orderlist(nodelist);
                break;
        default :
                break;
        }


    } while(choice != 7);

}

Node *makestartlist(){

    int i;
    Node *first=NULL, *parent=NULL, *node;

    // Declare array of structs
    Node students[10] = {
        {"Lars",10},
        {"Bent",7},
        {"Hans",9},
        {"Lise",3},
        {"Lone",5},
        {"Inger",6},
        {"Bo",11},
        {"Else",8},
        {"Atli",13},
        {"Jens",0}
    };

    for (i=0; i<10 ;i++){
        node = (Node*)malloc(sizeof(Node)); //Allocate memory
        if (i == 0) first = node;
        node -> name = students[i].name; //Add name
        node -> grade = students[i].grade; //Add grade
        node -> next = NULL;
        if (i>0) parent -> next = node;
        parent = node;
    }

    return first;
}

int listlength(Node* node){

    int count = 0;

    if (node != NULL){
        while(node != NULL){
            count++;
            node = node->next;
        }
    }
    else if (node == NULL){
        count = 0;
    }

    return count;
}

void gradelist(Node* node){

    printf("\n**********Show grade list*************\n");

    //Print linked list
    if (node != NULL){
        while(node != NULL){
            printf("Student: %s\tGrade: %d\n", node->name, node->grade);
          node = node->next;
        }
    }
    else {
        printf("No students!");
    }

    printf("*********************************************\n\n");

}

void orderlist(Node* node){

    /*
    head contains the first element from the original linked list
    remaining contatins the rest of the list
    */
    Node *head=NULL, *first_head=NULL, *remaining, *first=NULL, *parent=NULL;
    int i = 0, headlistlength;

    printf("Order list in increasing order\n");

    if (node != NULL){

        head = (Node*)malloc(sizeof(Node));
        head->name = node->name;
        head->grade = node->grade;
        head->next = NULL;

        node = node->next;

        while (node != NULL){
            remaining = (Node*)malloc(sizeof(Node));
            if (i == 0) first = remaining;
            remaining->name = node->name;
            remaining->grade = node->grade;
            remaining->next = NULL;
            if(parent != NULL) parent->next = remaining;
            parent = remaining;
            i++;
            node = node->next;
        }
    }

    remaining = first;

    sortlist(remaining, head);
}

void sortlist(Node* remaining, Node* head){

    int i = 0;

    Node *first_head = head, *current=head, *temp=head, *parent=head;

    int high = 0;

    while(remaining != NULL){
        current = head;

        // Virker
        if (listlength(head) == 1){
            if (remaining->grade > head->grade){
                temp = (Node*)malloc(sizeof(Node));
                temp->name = remaining->name;
                temp->grade = remaining->grade;
                temp->next = NULL;
                current->next = temp;
            }
            else{
                head = (Node*)malloc(sizeof(Node));
                head->name = remaining->name;
                head->grade = remaining->grade;
                head->next = current;
                first_head = head;
            }
        }
        else{
            // Virker
            if (remaining->grade <= head->grade){
                head = (Node*)malloc(sizeof(Node));
                head->name = remaining->name;
                head->grade = remaining->grade;
                head->next = current;
                first_head = head;
            }
            else{

                if (remaining->grade > head->grade){

                    high = get_high(current);
                    // Virker
                    if (high < remaining->grade){
                        temp = (Node*)malloc(sizeof(Node));
                        temp->name = remaining->name;
                        temp->grade = remaining->grade;
                        temp->next = NULL;
                        while(current->next != NULL){
                            current = current->next;
                        }
                        current->next = temp;
                        first_head = head;
                    }
                    // Virker IKKE :(
                    else{

                        while(current != NULL){

                            if (remaining->grade <= current->grade){
                                parent = current;
                                printf("Indsaet her!%d <= %d", remaining->grade, current->grade);
                                  temp = (Node*)malloc(sizeof(Node));
                                temp->name = remaining->name;
                                temp->grade = remaining->grade;
                                temp->next = parent;
                                head->next = temp;
                                  break;
                            }

                            current = current->next;
                        }
                        first_head = head;
                    }
                }
            }
        }

        gradelist(first_head);
        remaining = remaining->next;
    }
}

int get_high(Node* node){

    int high=0;
    while (node != NULL){
        if (node->grade > high) high = node->grade;
        node = node->next;
    }

    return high;
}
Avatar billede arne_v Ekspert
25. oktober 2003 - 21:16 #1
Hej igen.

:-)
Avatar billede arne_v Ekspert
25. oktober 2003 - 21:21 #2
temp->next = parent;
head->next = temp;

sætter temp ind efter head og før parent - altså head->temp->parent.

Er det meningen ?
Avatar billede arne_v Ekspert
25. oktober 2003 - 21:22 #3
Iøvrigt tror jeg at jeg ville lave den sortering noget anderledes.

Du burde kunne lave en sortering kun med ændringer af pointer til first
og manipulation af next pegepindene.
Avatar billede tchami Nybegynder
25. oktober 2003 - 21:24 #4
hej :)

Det er virkelig ikke fordi jeg er doven, jeg vil MEGET hellere lave det selv. Jeg har tegnet tegninger, lavet pseudo-kode, men jeg kan simpelthen ikke hitte ud af hvorfor det ikke virker.

Men nu holdt mit temperament ikke til at prøve mere, så tænkte jeg lige så godt kunne spørge dig :)

Bemærk dog at resten af "funktionerne" i sortering virker, så noget har jeg lavet ;)
Avatar billede tchami Nybegynder
25. oktober 2003 - 21:30 #5
Det er meningen at temp skal sættes ind før parent (da parent er større end temp), og det virker også (tror jeg), men de elementer før parent skal jo stadig være der. Derfor satte jeg head->next = temp, men det virker logisk nok ikke, da den så bare vil sætte det ind på den 2. plads i head og ikke på den n-te.

Men hvordan pokker gør jeg?
Avatar billede arne_v Ekspert
25. oktober 2003 - 22:00 #6
Jeg brygger på et eksempel !
Avatar billede tchami Nybegynder
25. oktober 2003 - 22:02 #7
Mange mange tak :)
Avatar billede arne_v Ekspert
25. oktober 2003 - 22:59 #8
#include <stdio.h>
#include <stdlib.h>

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

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;
    }
    else
    {
        last = *first;
        while(last->next!=NULL) last=last->next;
        last->next = extra;
    }
}

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 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 pointers */
                if(p2->next!=p1)
                {
                    temp = p2->next;
                    p2->next = p1->next;
                    p1->next = temp;
                    pp2->next = p2;
                }
                else
                {
                    p2->next = p1->next;
                    p1->next = p2;
                }
                if(pp1==NULL)
                {
                    *first = p1;
                }
                else
                {
                    pp1->next = p1;
                }
            }
            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);
  sort(&first);
  printf("sorteret:\n");
  print(first);
  add(&first, "d", 4);
  add(&first, "e", 5);
  printf("usorteret:\n");
  print(first);
  sort(&first);
  printf("sorteret:\n");
  print(first);
  return 0;
}
Avatar billede arne_v Ekspert
25. oktober 2003 - 22:59 #9
Output:

usorteret:
----------------
a 111
bb 22
ccc 3
----------------
sorteret:
----------------
ccc 3
bb 22
a 111
----------------
usorteret:
----------------
ccc 3
bb 22
a 111
d 4
e 5
----------------
sorteret:
----------------
ccc 3
d 4
e 5
bb 22
a 111
----------------
Avatar billede tchami Nybegynder
26. oktober 2003 - 00:35 #10
Hold da op, det var smart!

Jeg har siddet og tegnet for at forstå den nestede løkke, og det ser umiddelbart logisk nok ud, men hvis der mod forventning skulle være noget jeg ikke kan forstå, må jeg så spørge?

Smid et svar i øvrigt :)

Og mange tak for hjælpen endnu engang.
Avatar billede arne_v Ekspert
26. oktober 2003 - 00:41 #11
Jeg vil ikke engang afvise at det kan laves endnu smartere.

Men det var lige sådan jeg kunne kode det.

Der må være lidt ideer i det du kan bruge.
Avatar billede arne_v Ekspert
26. oktober 2003 - 00:41 #12
Og et svar.
Avatar billede arne_v Ekspert
26. oktober 2003 - 09:57 #13
En af de ting der er værd at bemærke er at jeg bruger pointer to pointer
for first fordi så kan jeg ændre hvad first peger på.
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