写在前面:一道朴实无华的课后题,但也折腾了好久。这是第三次数据结构实验课的唯二题之一,老师说过于难就延长了提交期限,嗯,确实挺难,或者说我太菜了呜呜。。。
我们都知道:异或操作满足结合律,于是就有如下式子成立
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;
}