一、异或指针双向链表的定义和原理
首先值得注意的是书上的定义写错了,注意应该是struct XorNode *LRPtr,星号必不可少!
typedef struct XorNode
{
int data;
struct XorNode *LRPtr;
} XorNode, *XorPointer;
这是一个双向链表,常规双向链表的方案是一个结点有两个指针域,分别指向这个结点的前驱和后继。但这个题里面的链表每个结点只有一个指针域,里面存放的是这个结点L前驱的地址值A与这个结点后驱的地址值B进行异或运算后的结果,就是L->LPPtr=A ^ B,所以在访问的时候,如果要访问L的后继,就用L的前驱地址值A与L指针域里的数进行异或运算,就是A ^ (A ^ B)=B,反过来,如果要访问L的前驱,就用L后继的地址值B与L指针域里的数进行异或运算,就是B^ (A ^ B)=A,这样就实现了节省空间,用每个结点只有一个指针域实现双向链表。
typedef struct
{
XorPointer Left,Right;
}XorLinkedList;
二、2-34 遍历输出异或指针双向链表
void PrintXorList(XorLinkedList A,int direction)//2-34 遍历输出异或指针双向链表
{
XorPointer p,pre=NULL,q=NULL;
if(direction==LEFT)p=A.Left; //从左边开始遍历
else p=A.Right; //从右边开始遍历
int count =0;
while(p!=NULL) //最后一个结点输出后,最后一个结点的指针域的值和它的前驱的地址值相同,
{ //异或结果为0,返回NULL指针,下次while判断退出循环
count++;
//cout<<p->data<<endl;
printf("%d\n",p->data);
q=Xorp(pre,p->LRPtr);
pre=p;
p=q;
}
}
三、2-35在异或指针双向链表第i个结点前插入结点a
Status InsertXorList(XorLinkedList &A,int i,XorPointer a)//2-35在异或指针双向链表第i个结点前插入结点a
{ //此处a结点需要提前malloc再进入函数
XorPointer prev=NULL,q=NULL;
XorPointer p=A.Left;
int count=1;//用于移动计数
if(i<=0) return ERROR;
if(p==NULL)//空表
{
A.Left=A.Right=a;
a->LRPtr=NULL;
return OK;
}
else if(i==1)//在第一个位置加入
{
q=Xorp(prev,p->LRPtr);
a->LRPtr=Xorp(prev,p);
p->LRPtr=Xorp(a,q);
A.Left=a;
return OK;
}
while(count<i&&p!=NULL)//移动到第i个位置,第i个位置为p
{
q=Xorp(prev,p->LRPtr);
prev=p;
p=q;
count++;
}
if(q==NULL)//在最后一个位置插入
{
if(count<i) return ERROR;//没有那么多结点,返回错误
prev=NULL;
p=A.Right;
q=Xorp(prev,p->LRPtr);
p->LRPtr=Xorp(q,a);
a->LRPtr=A.Right;
A.Right=a;
return OK;
}
else//在一般位置插入
{
XorPointer pprev,pp; //即在prev和p之间插入a,pp是p的后继,pprev是prev的前驱
pprev=Xorp(p,prev->LRPtr);
pp=Xorp(prev,p->LRPtr);
prev->LRPtr=Xorp(pprev,a);
p->LRPtr=Xorp(pp,a);
a->LRPtr=Xorp(prev,p);
return OK;
}
return ERROR;//上述操作均未return,则返回错误
}
四、完整代码,供读者自行验证
编译器:DEVC++。
#include<iostream>
#include<stdlib.h>
using namespace std;
#define Status int
#define ElemType int
#define OK 1
#define INFEASIBLE -1
#define ERROR -1
#define LEFT 1
#define RIGHT 2
typedef struct XorNode
{
int data;
struct XorNode *LRPtr;
} XorNode, *XorPointer;
typedef struct
{
XorPointer Left,Right;
}XorLinkedList;
XorPointer Xorp(XorPointer p,XorPointer q)//返回指针p和q的异或结果
{
long long x,y,z;
x=(long long) p;
y=(long long) q;
z=x^y;
return (XorPointer)z;
}
// cast from 'XorPointer {aka XorNode*}' to 'long unsigned int' loses precision [-fpermissive]
Status InitXorLinkList(XorLinkedList &L,int number) //生成一个链表用于调试,包含数值0-5
{
int count=1;
XorPointer p,q,prev;
for(int i=0;i<=number;i++)
{
p=(XorPointer)malloc(sizeof(XorNode));
p->data=i;
p->LRPtr=NULL;
if(i==0)
{
L.Left=p;
prev=NULL;
q=p;
}
else if(i!=number)
{
q->LRPtr=Xorp(prev,p);
prev=q;
q=p;
}
else if(i==number)
{
L.Right=p;
q->LRPtr=Xorp(prev,p);
p->LRPtr=Xorp(q,NULL); //是q和NULL异或,不是prev和p异或,脑残了,调试了好久!
}
}
}
void PrintXorList(XorLinkedList A,int direction)//2-34 遍历输出异或指针双向链表
{
XorPointer p,pre=NULL,q=NULL;
if(direction==LEFT)p=A.Left; //从左边开始遍历
else p=A.Right; //从右边开始遍历
int count =0;
while(p!=NULL) //最后一个结点输出后,最后一个结点的指针域的值和它的前驱的地址值相同,
{ //异或结果为0,返回NULL指针,下次while判断退出循环
count++;
//cout<<p->data<<endl;
printf("%d\n",p->data);
q=Xorp(pre,p->LRPtr);
pre=p;
p=q;
}
}
Status InsertXorList(XorLinkedList &A,int i,XorPointer a)//2-35在异或指针双向链表第i个结点前插入结点a
{ //此处a结点需要提前malloc再进入函数
XorPointer prev=NULL,q=NULL;
XorPointer p=A.Left;
int count=1;//用于移动计数
if(i<=0) return ERROR;
if(p==NULL)//空表
{
A.Left=A.Right=a;
a->LRPtr=NULL;
return OK;
}
else if(i==1)//在第一个位置加入
{
q=Xorp(prev,p->LRPtr);
a->LRPtr=Xorp(prev,p);
p->LRPtr=Xorp(a,q);
A.Left=a;
return OK;
}
while(count<i&&p!=NULL)//移动到第i个位置,第i个位置为p
{
q=Xorp(prev,p->LRPtr);
prev=p;
p=q;
count++;
}
if(q==NULL)//在最后一个位置插入
{
if(count<i) return ERROR;//没有那么多结点,返回错误
prev=NULL;
p=A.Right;
q=Xorp(prev,p->LRPtr);
p->LRPtr=Xorp(q,a);
a->LRPtr=A.Right;
A.Right=a;
return OK;
}
else//在一般位置插入
{
XorPointer pprev,pp; //即在prev和p之间插入a,pp是p的后继,pprev是prev的前驱
pprev=Xorp(p,prev->LRPtr);
pp=Xorp(prev,p->LRPtr);
prev->LRPtr=Xorp(pprev,a);
p->LRPtr=Xorp(pp,a);
a->LRPtr=Xorp(prev,p);
return OK;
}
return ERROR;//上述操作均未return,则返回错误
}
int main()
{
XorLinkedList A;
InitXorLinkList(A,5);
cout<<"已生成一个异或指针双向链表,共六个节点,包含数值0-5."<<endl;
cout<<"左端输出:"<<endl;
PrintXorList( A,LEFT);
cout<<"右端输出:"<<endl;
PrintXorList( A,RIGHT);
XorPointer a;
cout<<"先执行插入操作,从左端插入"<<endl;
cout<<"result 结果为1则插入成功,为-1为插入失败"<<endl;
while(1)
{
int i;
cout<<"请输入插入的位置:"<<endl;
cin>>i;
a=(XorPointer)malloc(sizeof(XorNode));
cout<<"请输入结点数值:"<<endl;
cin>>a->data;
int judge= InsertXorList(A,i,a);
cout<<"the result is "<<judge<<endl;
cout<<"左端输出:"<<endl;
PrintXorList( A,LEFT);
}
}