2010-03-15 3 views
1

Я новичок в C, и я работаю над связанным списком XOR для проекта. У меня есть большая часть кода, но я не могу заставить функцию удаления из списка работать правильно. Кажется, он может удалить некоторые числа, но не любое число, которое вы передаете в функцию. Может ли кто-нибудь, кто испытал С, взглянуть и, возможно, указать, где я ошибся? Я работал над этим некоторое время и не имел большой удачи, и я начал более 3 раз :(Любая помощь очень ценится. Спасибо. Вы можете увидеть мою первую попытку кода here. Могу только опубликовать одну ссылку , так что если вы хотели бы видеть свою вторую попытку, просто скажи мне, так и я могу отправить его к вам или что-то Спасибо за ваше времяПроблемы со связанным списком в C

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

struct node { 
     int data; 
     unsigned long link; 
}; 
struct node *head, *tail, *currN, *prevN, *nextN, *tmp; 

void insert(struct node **headN, struct node **tailN, int n); 
void delete(struct node **headN, struct node **tailN, int n); 
void list(struct node *head, int i); 
void nextNode(); 
void previNode(); 

//============================================================ 

void insert(struct node **headN, struct node **tailN, int numN) { 
    struct node *newnode = malloc(sizeof(struct node)); 
    newnode->link =(unsigned long)(*headN); 
    newnode->data = numN; 

    //if empty list 
    if (*headN == NULL){ 
      *headN = newnode; 
      currN = *headN; 
      (*headN)->link = 0; 
    } else if ((*headN)->link == (unsigned long)NULL){ 
      if (numN <= (*headN)->data){ 
       newnode->link = (unsigned long) *headN; 
       (*headN)->link = (unsigned long) newnode; 
       tail = *headN; 
       *headN = newnode; 
       nextN = tail; 
       prevN = NULL; 
      } else { 
       newnode->link = (unsigned long) *headN; 
       (*headN)->link = (unsigned long) newnode; 
       tail = newnode; 
       nextN = NULL; 
       currN = tail; 
       prevN = *headN; 
       } 
    } else { 
      currN = *headN; 
      prevN = NULL; 
      nextN = (struct node *)(currN->link^(unsigned long) prevN); 
      if (numN > tail->data){ 
       while (currN!=tail){ 
        nextNode(); 
       } 
       newnode->link = (unsigned long) currN; 
       currN->link = (unsigned long) newnode^(unsigned long) prevN; 
       tail = newnode; 
      } else if (numN < head->data){ 
       currN->link = (unsigned long) newnode^(unsigned long) nextN; 
       newnode->link = (unsigned long) currN; 
       *headN = newnode; 
       nextN = currN; 
       currN = *headN; 
      } else { 
       while (numN > currN->data){ 
        nextNode(); 
       } 
       newnode->link = (unsigned long) prevN^(unsigned long) currN; 
       prevN->link ^= (unsigned long) currN^(unsigned long) newnode; 
       currN->link ^= (unsigned long) prevN^(unsigned long) newnode; 
      } 
    } 
} 

void delete(struct node **headN, struct node **tailN, int numD){ 

    struct node *prevN = NULL; 
    struct node *currN = *headN; 

    while (currN != NULL) 
    { 
     struct node *nextN = (struct node *) (currN->link^(unsigned long)prevN); 
     //if the number is found, then delete it 
     if (currN->data == numD) 
     { 
      if(prevN) 
        { 
        prevN->link ^= (unsigned long)currN^(unsigned long)nextN; 
       } 
        else 
        *headN = nextN; 
       if(nextN) 
        { 
        nextN->link ^= (unsigned long)currN^(unsigned long)prevN; 
        } 
        else 
        *tailN = prevN; 
      free(currN); 
      break; 
     } 
      prevN = currN; 
     currN = nextN; 
    } 
} 

void list(struct node *head, int i){ 

    if(i == 0){ 
    currN = head; 
    prevN = NULL; 
    int count = 1; 
    nextN = (struct node *) (currN->link^(unsigned long) prevN); 
    printf("Linked List in ascending order\n"); 
    while(currN!=NULL){ 
      if(count <= 10){ 
       printf("%-5d", currN->data); 
       nextNode(); 
       count++; 
      } 
      else{ 
       printf("\n"); 
       count = 1; 
      } 
    } 
    } 
    printf("\n\n"); 

    if(i == 1){ 
    printf("Linked List in descending order\n"); 
    currN = tail; 
    int count2 = 1; 
    prevN = (struct node *) currN->link; 
    nextN = NULL; 
    while (currN!=NULL){ 
     if(count2 <= 10){ 
       printf("%-5d", currN->data); 
       previNode(); 
       count2++; 

      }else{ 
       printf("\n"); 
       count2 = 1; 
      } 
    } 
    } 
    printf("\n");   
} 

void nextNode(){ 
    nextN = (struct node *) (currN->link^(unsigned long) prevN); 
    prevN = currN; 
    currN = nextN; 
} 

void previNode(){ 
    prevN = (struct node *) (currN->link^(unsigned long) nextN); 
    nextN = currN; 
    currN = prevN;  
} 

int main(){ 

    int i, num; 
    float seed; 
    head = NULL; tail = NULL; currN = NULL; prevN = NULL; nextN = NULL; 

    init_seed(1234567); 
    set_range(1,9999); 
    //inserting data into the linked list 
    for (i=0; i<100; ++i){ 
     num = rndm(); 
     insert(&head, &tail, num); 
    } 

    list((struct node*)head, 0); 
    //delete((struct node**)head, (struct node**)tail, 45); 
    //delete((struct node**)head, (struct node**)tail, 4040); 
    //delete((struct node**)head, (struct node**)tail, 9769); 
    list((struct node*)head, 1); 


    return 0; 
} 
+2

Пожалуйста, задайте конкретный вопрос, ваш код слишком долго читать. – zellio

+0

WTF - это связанный с XOR список? :-) – paxdiablo

+0

Можете ли вы определить части кода, где вы нажимаете seg-fault? – dirkgently

ответ

0

примечание о вашем коде:..

node.link не должен быть unsigned long, так как это предполагает характеристики вашего компилятора/платформы.

EDIT: Возможно, я ошибаюсь d на связанном списке XOR, обсуждение.

EDIT 2: (как предложил @Matthew Flaschen) используйте intptr_t, чтобы сделать ваш код более портативным.

+0

Почему это должен быть «узел структуры»? И это должен быть комментарий. –

+0

@tusbar Хорошо, с связанным списком XOR, возможно, не так просто, но похоже, что код предполагает, что размер ссылки на узел i того же размера, что и unsigned long int, что справедливо только для некоторых платформ/составители. –

+0

Это правда, на LLP64 'sizeof (ptr)' - 64 бита, а 'sizeof (long)' равно 32. –

5

Похоже, вы взяли какой-то код в Интернете и попытались его использовать.

Код работает нормально, вы просто не знаете, что такое указатель.

Вы делаете:

delete((struct node**)head, (struct node**)tail, 45); 

А вот определения переменных head и tail:

struct node { 
    int data; 
    unsigned long link; 
}; 
struct node *head, *tail, *currN, *prevN, *nextN, *tmp; 

Прототип функции delete() является void delete(struct node **headN, struct node **tailN, int numD);

«О, компилятор просит struct node **, давайте бросим его ». Это не так, как это работает.

Попробуйте это:

delete(&head, &tail, 45); 
+0

Хорошо, поэтому, используя & head & & tail, я прохожу по адресу справа? Я попробовал это, 45 удалось удалить только штраф, но когда я попытался удалить 4040 и 9769, они, похоже, не удалялись, потому что они все еще отображаются в списке, когда я печатаю его после вызова функции удаления. – seePhor

+0

http://codepad.org/wWW5ZUHS –

+0

что вы сделали/изменили? – seePhor

-1

Глядя на функции delete заставляет меня задаться вопросом об этой манипуляции указателя, кстати, вы используете адреса параметров, так действительно должно быть delete(&head, &tail, 45);

двигаться дальше от ....

 
void delete(struct node **headN, struct node **tailN, int numD) 
{ 
    struct node *prevN = NULL; 
    struct node *currN = *headN; 
    struct node *tempNode = NULL; 

    while (currN != NULL) 
    { 
     struct node *nextN = (struct node *) (currN->link^(unsigned long)prevN); 
     //if the number is found, then delete it 
     if (currN->data == numD) 
     { 
      if(prevN) 
      prevN->link ^= (unsigned long)currN^(unsigned long)nextN; 
      else 
      *headN = nextN; 
      if(nextN) 
      nextN->link ^= (unsigned long)currN^(unsigned long)prevN; 
      else 
      *tailN = prevN; 
      /* Sanity check here...you could be screwing up the list 
      ** by calling free(currN) 
      */ 
      tempNode = currN; 
      free(tempNode); 
      /* free(currN); <-- That could be misleading... */ 
      break; 
     } 
     prevN = currN; 
     currN = nextN; 
    } 
} 

Эта поправка к коду, чтобы убедиться, что currN соответствует, глядя на с глазами на манипуляции с указателем, которые могут быть сомнительными, так как список может быть разбит, сделав free на currN ... только для того, чтобы быть в безопасности ...

+1

Я не вижу, что делает ваша поправка. currN удаляется из списка, поэтому узел освобождается. Вы делаете то же самое, просто с дополнительной переменной указателя. Конечно, 'prevN = currN; currN = nextN; 'не выполняются из-за' break' (в этом случае разрыв фактически является «возвратом») –

+0

Это сработало! Итак, какие проблемы были бесплатными (currN), вызвавшими именно? – seePhor

+0

@seePhor: Я на самом деле думал о том, что при повторении через связанный список, например '' while (currN! = Null) ', то currN может быть освобожден и сломать цикл while ... следовательно, необходимо временно назначить его другой указатель на освобождение ... tempNode = currN; currN = currN-> next; бесплатно (tempNode); возможно, я перепутался ... и думал, что это применимо здесь ... – t0mm13b

Смежные вопросы