简体   繁体   中英

Problems with Linked List in C

I am new to C and I am working on an XOR linked list for a project. I have most of the code done, but I can't seem to get the delete function of the list to work properly. It seems able to delete some numbers, but not any number you pass into the function. Could anyone experienced with C take a look and possibly point out where I went wrong? I have been working on this for a while now and have not had much luck and I have started over 3 times :( Any help is much appreciated. Thank you. You can see my first attempt of code here . I can only post one link, so if you would like to see my second attempt, just tell me so and I can email it to you or something. Thank you for your time.

#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;
}

It looks like you took some code on the internet and tried to use it.

The code works just fine, you just don't know what a pointer is.

You're doing:

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

And here are the definitions of the variables head and tail :

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

The prototype for the delete() function is void delete(struct node **headN, struct node **tailN, int numD);

"Oh the compiler is asking for struct node ** , let's cast it". That's not how it works.

Try this:

delete(&head, &tail, 45);

A note about your code:

The node.link should not be a unsigned long it since this assumes characteristics of you compiler/platform.

EDIT: Maybe I missed out on the XOR linked list, discussion.

EDIT 2: (as suggested by @Matthew Flaschen) use intptr_t to make your code more portable.

Looking at the delete function makes me wonder about this pointer manipulation, by the way, you are using address-of parameters so really it should be delete(&head, &tail, 45);

moving on from that....

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;
   }
}

That amendment to the code is to ensure that currN is consistent, looking at with eyes on the pointer manipulation, that could be questionable, as the list could end up broken by doing a free on the currN ...just to be safe...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM