【问题标题】:C code for XOR linked listXOR链表的C代码
【发布时间】:2011-04-01 17:04:25
【问题描述】:

我一直在尝试实现XOR linked list 及其操作,但我无法正确完成。

异或链表涉及地址操作,是否可以用C实现?

如果能给出一些实际的工作代码,我将非常感激。

【问题讨论】:

  • 不,这不是家庭作业。我正在尝试出于自己的兴趣来实施它
  • 到目前为止你做了什么?什么不工作?
  • 我试图将每个指针地址存储在一个单独的列表中,并尝试使用它们来获取 XOR 链接列表的地址字段。但是我在处理指针时遇到了很多逻辑错误

标签: c linked-list xor


【解决方案1】:

这是我以前从未见过的有趣想法。在当今相当丰富的内存中,看起来很复杂却收效甚微(尽管并非所有平台都充满了内存)。 编辑 在做我真正的工作时,我的思绪不断地回到它,所以我添加了创建新节点并将其放在给定端的函数。现在更漂亮了。 addnode 和 traverse 函数都是对称的,这很酷。两者都不需要知道方向。只需将其放在列表的一端,它们就会正常运行。

根据 Darron 的评论(谢谢),为了便于移植,我将 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 );


}

【讨论】:

  • 您应该使用 intptr_t 使此代码具有可移植性。在某些平台上,指针不适合 unsigned int。
  • 曾几何时,每个称职的程序员都知道这一点,因为这是 Knuth Vol. 中的一个练习。 1
【解决方案2】:

由于您不能对指针执行异或操作,您必须将地址转换为整数类型以执行异或并将结果转换回右指针类型。

据我所知,C99 只有两种整数类型可以保证与具有定义行为的指针之间的转换(= 取回您的原始指针):intptr_t&lt;stdint.h&gt; 中的 uintptr_t。请注意,这两种类型都是可选的,因此您的实现可能没有它们。

转换示例,假设ab 是指向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 * 的额外演员表,如果不是,请有人纠正我。有关 (u)intptr_t 类型的更多信息,请参阅 C99 标准的 §7.18.1.4。

【讨论】:

  • 我认为确实需要强制转换为void*。该标准仅保证void*(u)intptr_t 之间的转换(如果它们如您所说),然后在指向数据类型的指针和void* 之间进行转换。但它没有说明直接演员,所以你应该避免它是安全的。
【解决方案3】:

由于XOR链接列表涉及地址操作,是否可以在C中实现它?

是的。地址是指针,指针是数字*,数字允许异或(即a ^ b)。

Look up what 已经完成了,你应该可以进行实现了。

*至少,您可以将它们视为数字 - 不过可能需要显式转换。

【讨论】:

  • 你能举一些这样的演员吗?我只是有问题!!!
  • @Shyam: void* ptr = ...; unsigned val = (unsigned)ptr; 但我认为您不必从指向 C 中的整数类型的指针显式转换,因此您只需执行 unsigned val = ptr;
  • @Job: no 转换为unsigned 未由标准定义,如果可能,甚至可能导致信息丢失。 unsigned 和指针可能有不同的宽度。
  • @Job:要转换为的类型是uintptr_tintptr_t
猜你喜欢
  • 2014-09-15
  • 2014-04-17
  • 2019-06-03
  • 2013-03-04
  • 2017-04-11
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
  • 2022-01-10
相关资源
最近更新 更多