严题集 2-34遍历输出异或指针双向链表的值 && 2-35 在异或指针双向链表中第i个结点前插入一个结点(附完整代码)

一、异或指针双向链表的定义和原理

首先值得注意的是书上的定义写错了,注意应该是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); 
	}	
}
发布了6 篇原创文章 · 获赞 2 · 访问量 96

猜你喜欢

转载自blog.csdn.net/HUST_LHC/article/details/105259535