循环链表--使用前后指针的异或寻找节点

写在前面:一道朴实无华的课后题,但也折腾了好久。这是第三次数据结构实验课的唯二题之一,老师说过于难就延长了提交期限,嗯,确实挺难,或者说我太菜了呜呜。。。

我们都知道:异或操作满足结合律,于是就有如下式子成立

                                         b==(a^a)^b==a^(a^b)

同时指针也可以进行运算操作,只不过要强制转换成 size_t 类型,查了才知道。。

 

 一个抽象的抽象图(里面的一个方块就是一个节点),prev_xor_next 是前后两个节点的地址的异或,所以已知前一个节点的地址加当前节点的prev_xor_next 元素的值,就能通过两者的异或得到下一个节点的地址。

节点定义如下,element 是数据元素,prev_xor_next 是两节点地址的异或

class _node {
    public:
      E element;
      long prev_xor_next;
  };

链表的模板类定义如下,同时重载了一个输出,只需完成下面的模板实现即可。

template <typename E>
class list {
  class _node {
    public:
      E element;
      long prev_xor_next;
  };
  
  _node * _head;
  _node * _tail;
  long _size;
  
public:
  list();
  int size() const;
  void clear();
  void insert(int index, const E & e);
  int find(const E & e) const;
  void remove(int index);
  ~list();
  E & operator [] (int index);
  const E & operator [] (int index) const;
};

template <typename E>
ostream & operator << (ostream & o, const list<E> & ll);

构造函数

很简单,完成几个赋值即可

template <typename E>
list<E>::list(){
    _head=_tail=nullptr;
    _size=0;
}

size() 函数

返回 _size 的值

template <typename E>
int list<E>::size() const{
    return _size;
}

 clear() 函数

以下的全部遍历操作都可以仿照这个来写(指复制粘贴),但也有些许不同

template <typename E>
void list<E>::clear(){
	_node *prev=_tail, *pnow=_head, *next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
	while(pnow!=_tail){
		prev=pnow;
		delete pnow;
		pnow=next;
		next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
	}
	delete pnow;
	_head=_tail=nullptr;
	_size=0;
}

insert() 函数

0个节点和1个节点时插入会有不同需要单独写,其他情况都是相同的操作

template <typename E>
void list<E>::insert(int index, const E & e){
	if(index<0||index>_size) exit(112233);
	if(_size==0){
		_head=new _node{e,0};
		_tail=_head;
	}
	else if(_size==1){
		if(index==0) _head=new _node{e,0};
		else if(index==1) _tail=new _node{e,0};
	}
	else{
		_node *prev=_tail, *pnow=_head, *next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
		int temp_index=0;
		while(temp_index<index){
			prev=pnow;
			pnow=next;
			next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
			temp_index++;
		}
		_node *prev_prev=(_node*)((size_t)prev->prev_xor_next^(size_t)pnow);
		_node *new_node=new _node{e,(long)((size_t)prev^(size_t)pnow)};
		prev->prev_xor_next=(long)((size_t)prev_prev^(size_t)new_node);
		pnow->prev_xor_next=(long)((size_t)next^(size_t)new_node);
		if(index==0) _head=new_node;
		else if(index==_size) _tail=new_node;
	}
	_size++;
}

find() 函数

注意链表为空时要返回-1,否则会报错,因为next在声明时访问了pnow的元素,而此时pnow为nullptr

template <typename E>
int list<E>::find(const E & e) const{
	if(_size==0) return -1;
	_node *prev=_tail, *pnow=_head, *next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
	int index=0;
	while(index<_size){
		if(pnow->element == e) return index;
		prev=pnow;
		pnow=next;
		next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
		index++;
	}
	return -1;
}

remove() 函数

0节点、1节点、2节点时会有特殊情况,要更改头尾指针,其余情况操作一致

template <typename E>
void list<E>::remove(int index){
	if(index<0||index>=_size) exit(220022);
	if(_size==0) return;
	if(_size==1){
		if(_head) delete _head;
		_head=_tail=nullptr;
	}
	else if(_size==2){
		if(index==0){
			delete _head;
			_head=_tail;
		}
		else{
			delete _tail;
			_tail=_head;
		}
	}
	else{
		_node *prev=_tail, *pnow=_head, *next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
		int temp_index=0;
		while(temp_index<index){
			prev=pnow;
			pnow=next;
			next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
			temp_index++;
		}
		_node* prev_prev=(_node*)((size_t)prev->prev_xor_next^(size_t)pnow);
		_node* next_next=(_node*)((size_t)next->prev_xor_next^(size_t)pnow);
		next->prev_xor_next=(long)((size_t)next_next^(size_t)prev);
		prev->prev_xor_next=(long)((size_t)prev_prev^(size_t)next);
		if(_head==pnow) _head=next;
		if(_tail==pnow) _tail=prev;
		delete pnow;
	}
	_size--;
}

析构函数

直接调用 clear() 即可

template <typename E>
list<E>::~list(){
	list<E>::clear();
}

对 [ ] 的重载

两个写一样就行

template <typename E>
E & list<E>::operator [] (int index){
	if(index<0||index>=_size||_size==0) exit(9999);
	_node *prev=_tail, *pnow=_head, *next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
	int temp_index=0;
	while(temp_index<index){
		prev=pnow;
		pnow=next;
		next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
		temp_index++;
	}
	return pnow->element;
}

template <typename E>
const E & list<E>::operator [] (int index) const{
	if(index<0||index>=_size||_size==0) exit(9999);
	_node *prev=_tail, *pnow=_head, *next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
	int temp_index=0;
	while(temp_index<index){
		prev=pnow;
		pnow=next;
		next=(_node*)((size_t)pnow->prev_xor_next^(size_t)prev);
		temp_index++;
	}
	return pnow->element;
}

对 << 的重载

template <typename E>
ostream & operator << (ostream & o, const list<E> & ll){
	for(int i=0;i<ll.size();i++){
		o << ll[i] << ' ';
	}
	return o;
}

主函数

#include <iostream>
#include <string>
using namespace std;

#include "list.h"
#include "list.cpp"

int main() {
  list<char> ll;
  for (int i = 0; i < 100; ++ i) {
    string action;
    string ch;
    cin >> action;
    if (action=="insert") {
      	int index = 0;
      	cin >> ch >> index;
      	index %= (ll.size()+1);
     	ll.insert(index, ch[0]);
      	cout << "在第 " << index << " 个节点处插入数据为 " << ch[0] << " 的新节点" << endl;
    }
    if (action=="remove") {
    	cin >> ch;
      	int index = ll.find(ch[0]);
      	if (index!=-1) {
      	  	ll.remove(index);
       	 	cout << "移除第 " << index << " 个节点" << endl;
      	}
    }
    if (action=="find") {
    	cin >> ch;
      	cout << ch << "在链表第 " << ll.find(ch[0]) << " 个节点处(从0开始计数)" << endl;
    }
    if (action=="clear") {
    	cout << "总共清除 " << ll.size() << " 个节点" << endl;
    	ll.clear();
	}
    cout << "目前共有 " << ll.size() << " 个节点" << endl <<"链表元素如下:" << ll << endl << endl;
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值