Kod C dla listy łączonej XOR

Próbowałem zaimplementować XOR linked list i jej operacje, ale nie byłem w stanie zrobić tego poprawnie.

Czy jest możliwe zaimplementowanie go w C skoro lista linków XOR obejmuje operacje na adresach?

Byłbym bardzo wdzięczny, gdyby podany został jakiś działający kod.

Author: Andrew Medico, 2010-08-20

3 answers

To ciekawy pomysł, którego wcześniej nie widziałem. Przy dzisiejszej dość obfitej pamięci, wydaje się, że jest to dużo złożoności za niewielki zysk (chociaż nie wszystkie platformy są równo z pamięcią). Edit podczas wykonywania mojej prawdziwej pracy, mój umysł wciąż dryfował do niej, więc dodałem funkcję do tworzenia nowego węzła i umieścić go na podanym końcu. Teraz ładniejsza. Fajnie, że zarówno funkcje addnode, jak i traverse są symetryczne. Ani nie musi znać kierunku. Po prostu daj to jeden koniec listy i działają poprawnie.

I bazując na komentarzu Darrona (dzięki), zmieniłem int na intptr_t dla przenośności.

#include <stdio.h>
#include <malloc.h>
#include <stdint.h>  // gcc needs this for intptr_t.  

typedef struct xorll {
   int  value;
   struct xorll  *np;
}  xorll;


// traverse the list given either the head or the tail
void traverse( xorll *start )  // point to head or tail
{
   xorll *prev, *cur;

   cur = prev = start;
   while ( cur )
      {
      printf( "value = %d\n", cur->value );
      if ( cur->np == cur )
         // done
         break;
      if ( cur == prev )
         cur = cur->np;   // start of list
      else {
         xorll *save = cur;
         cur = (xorll*)((uintptr_t)prev ^ (uintptr_t)cur->np);
         prev = save;
         }
      }
}

// create a new node adding it to the given end and return it
xorll* newnode( xorll *prev, xorll *cur, int value )
{
   xorll *next;

   next = (xorll*)malloc( sizeof( xorll ));
   next->value = value;
   next->np = cur;  // end node points to previous one

   if ( cur == NULL )
      ; // very first node - we'll just return it
   else if ( prev == NULL ) {
      // this is the second node (they point at each other)
      cur->np = next;
      next->np = cur;
      }
   else {
      // do the xor magic
      cur->np = (xorll*)((uintptr_t)prev ^ (uintptr_t)next);
      }

   return next;
}



int main( int argc, char* argv[] )
{
   xorll *head, *tail;
   int   value = 1;

   // the first two nodes point at each other.  Weird param calls to
   // get the list started
   head = tail = newnode( NULL, NULL, value++ );
   tail = newnode( NULL, tail, value++ );

   // now add a couple to the end
   tail = newnode( tail->np, tail, value++ );
   tail = newnode( tail->np, tail, value++ );

   // this is cool - add a new head node
   head = newnode( head->np, head, 999 );


   printf( "Forwards:\n" );
   traverse( head );
   printf( "Backwards:\n" );
   traverse( tail );


}
 15
Author: Mark Wilkins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-20 17:59:19

Ponieważ nie możesz wykonywać operacji xor na wskaźnikach, będziesz musiał przekonwertować adresy na typ integer, aby wykonać xor i przekonwertować wynik z powrotem na typ prawego wskaźnika.

Z tego co wiem, C99 ma tylko dwa typy liczb całkowitych, które gwarantują konwersję do i ze wskaźników o zdefiniowanym zachowaniu (=odzyskanie oryginalnego wskaźnika): intptr_t i uintptr_t z <stdint.h>. Zauważ, że oba typy są opcjonalne, więc twoja implementacja może ich nie mieć.

Przykład konwersje, zakładając, że a i b są poprawnymi wskaźnikami do struct node:

#include <stdint.h>

/* creating an xor field */
uintptr_t x = (uintptr_t) (void *) a ^ (uintptr_t) (void *) b;
/* reconstructing an address */
a = (void *) (x ^ (uintptr_t) (void *) b);

Nie jestem w 100% pewien, że dodatkowe odlewy do {[7] } są potrzebne, niech ktoś mnie poprawi, jeśli nie są. Więcej informacji na temat typów (u)intptr_t można znaleźć w §7.18.1.4 standardu C99.

 8
Author: schot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-20 15:36:24

Czy jest możliwe zaimplementowanie go w C skoro lista linków XOR obejmuje operacje na adresach??

Tak. Adresy są wskaźnikami, wskaźniki są liczbami* , a liczby pozwalają na XOR (tj. a ^ b).

Look up co jest zrobione i powinieneś być w stanie wykonać implementację.

* przynajmniej możesz myśleć o nich jako o liczbach - wyraźne rzuty mogą być jednak wymagane.

 5
Author: Dario,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-20 14:49:06