XOR链表的C代码

XOR链表的C代码,c,linked-list,xor,C,Linked List,Xor,我一直在尝试实施和实施它的操作,但我没有能够正确地做到这一点 因为XOR链接列表涉及地址操作,所以可以在C中实现它吗 如果给出一些实际的工作代码,我将非常感激 因为XOR链接列表涉及地址操作,所以可以在C中实现吗 是的。地址是指针,指针是数字*,数字允许异或(即a^b) 完成了什么,您应该能够执行 *至少,您可以将它们视为数字—但可能需要显式强制转换。由于无法对指针执行xor操作,因此必须将地址转换为整数类型才能执行xor,并将结果转换回右指针类型 据我所知,C99只有两种整数类型,它们可以保证

我一直在尝试实施和实施它的操作,但我没有能够正确地做到这一点

因为XOR链接列表涉及地址操作,所以可以在C中实现它吗

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

因为XOR链接列表涉及地址操作,所以可以在C中实现吗

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

完成了什么,您应该能够执行


*至少,您可以将它们视为数字—但可能需要显式强制转换。

由于无法对指针执行xor操作,因此必须将地址转换为整数类型才能执行xor,并将结果转换回右指针类型

据我所知,C99只有两种整数类型,它们可以保证与具有定义行为的指针之间的转换(=取回原始指针):
intptr\u t
uintpr\u t
。请注意,这两种类型都是可选的,因此您的实现可能没有它们

转换示例,假设
a
b
是指向
struct节点的有效指针

#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);
#包括
/*创建异或字段*/
无效*)a^(无效*)b;
/*重建地址*/
a=(无效*)(x^(无效*)b);

我不是100%确定是否需要对
void*
进行额外的强制转换,如果不需要,请有人纠正我。有关
(u)intptr\u t
类型的更多信息,请参见C99标准的§7.18.1.4。

这是一个有趣的想法,我以前从未见过。在今天相当丰富的内存中,这似乎是一个复杂的过程,但收获甚微(尽管并非所有平台都使用内存)编辑在做我的实际工作时,我的思绪不断地回到它,所以我添加了创建新节点的功能,并将其放在给定的一端。现在更漂亮了。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 );


}
#包括
#包括
#include//gcc需要这个接口。
类型定义结构xorll{
int值;
结构xorll*np;
}xorll;
//遍历给定头部或尾部的列表
无效遍历(xorll*start)//指向头部或尾部
{
xorll*上一个,*当前;
cur=prev=start;
while(cur)
{
printf(“值=%d\n”,cur->value);
如果(cur->np==cur)
//完成
打破
if(cur==prev)
cur=cur->np;//列表开始
否则{
xorll*保存=当前;
cur=(xorll*)((uintpttr_t)prev^(uintpttr_t)cur->np);
prev=保存;
}
}
}
//创建一个新节点,将其添加到给定端并返回
xorll*newnode(xorll*prev,xorll*cur,int值)
{
xorll*下一步;
next=(xorll*)malloc(sizeof(xorll));
下一步->值=值;
next->np=cur;//结束节点指向上一个节点
如果(cur==NULL)
;//第一个节点-我们将返回它
else if(prev==NULL){
//这是第二个节点(它们相互指向)
cur->np=next;
next->np=cur;
}
否则{
//做异或魔术
cur->np=(xorll*)((uintpttr)prev^(uintpttr)next);
}
下一步返回;
}
int main(int argc,char*argv[])
{
xorll*头,*尾;
int值=1;
//前两个节点彼此指向对方
//开始列表
head=tail=newnode(NULL,NULL,value++);
tail=newnode(NULL,tail,value++);
//现在在末尾添加一对
tail=newnode(tail->np,tail,value++);
tail=newnode(tail->np,tail,value++);
//这很酷-添加一个新的头部节点
head=newnode(head->np,head,999);
printf(“转发:\n”);
导线(头部);
printf(“向后:\n”);
横移(尾部);
}

不,这不是家庭作业。我是为了我自己的利益而实施的你到目前为止做了什么?什么不起作用?我尝试将每个指针地址存储在一个单独的列表中,并尝试使用它们获取XOR链接列表的地址字段。但是我在处理指针时遇到了很多逻辑错误,你能举一些这样的例子吗???我只有这个问题@Shyam:
void*ptr=。。。;无符号val=(无符号)ptrunsigned val=ptr
@Job:no标准未定义对
未签名的
的转换,如果可能,甚至可能导致信息丢失<代码>无符号
和指针的宽度可能不同。@作业:要强制转换到的类型是
uintpr\u t
intptr\u t
。您应该使用intptr\t使此代码可移植。在某些平台上,指针不适合无符号int。曾几何时,每一个称职的程序员都知道这一点,因为这是Knuth第1卷中的一个练习。我认为确实有必要转换为
void*
。该标准仅保证
void*
(u)intptr\u t
(如果您所说的存在)之间的转换,以及指向数据类型的指针和
void*
之间的转换。但是它在直播上没有说明什么,所以为了安全起见,你应该避免使用它。