Код C для связанного списка XOR - PullRequest
11 голосов
/ 20 августа 2010

Я пытался реализовать связанный список XOR и его операции, но я не смог сделать это правильно.

Возможно ли реализовать его в C, поскольку список ссылок XOR включает операции с адресами?

Я был бы очень благодарен, если бы был дан какой-то действующий рабочий код.

Ответы [ 3 ]

16 голосов
/ 20 августа 2010

Это интересная идея, которую я не видел раньше.С сегодняшним довольно большим количеством памяти, это кажется большой сложностью для небольшого выигрыша (хотя не все платформы заполнены памятью). Редактировать Выполняя свою настоящую работу, мой разум продолжал возвращаться к нему, поэтому я добавил функцию для создания нового узла и поместил его в заданный конец.Красивее сейчас.Довольно круто, что функции addnode и traverse симметричны.Никто не должен знать направление.Просто дайте ему один конец списка, и они будут работать правильно.

И, основываясь на комментарии Даррона (спасибо), я изменил int на intptr_t для переносимости.

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


}
9 голосов
/ 20 августа 2010

Поскольку вы не можете выполнять операции xor над указателями, вам придется преобразовать адреса в целочисленный тип, чтобы выполнить xor, и преобразовать результат обратно в тип указателя вправо.

Насколько мне известно, в C99 есть только два целочисленных типа, которые гарантируют преобразование в указатели с определенным поведением (и обратно в исходный указатель): Обратите внимание, что оба типа являются необязательными, поэтому ваша реализация может не иметь их.

Пример преобразования при условии, что a и b являются действительными указателями на 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);

Я не уверен на 100%, нужны ли дополнительные приведения к void *, кто-нибудь, пожалуйста, исправьте меня, если это не так. См. §7.18.1.4 стандарта C99 для получения дополнительной информации о типах (u)intptr_t.

5 голосов
/ 20 августа 2010

Возможно ли реализовать это в C, поскольку список ссылок XOR включает операции с адресами ??

Да, это так.Адреса являются указателями, указатели являются числами *, а числа допускают XOR (т. Е. a ^ b).

Посмотрите , что сделано , иВы должны быть в состоянии сделать реализацию.

* По крайней мере, вы можете думать о них как о числах - хотя может потребоваться явное приведение.

...