算法导论::第三部分::第10章(上)

数据结构

10基本数据结构

10.1栈和队列

  栈和队列的主要区别在于元素的插入和删除方式的不同,栈实现的是后进先出策略(Last-in first-out, LIFO),而队列采用的是先进先出策略(First-in first-out,FIFO)。

  

#include<iostream>
#include<vector>

using namespace std;

struct Stack{
public:
	Stack(vector<int> v):vec(v),top(-1){}
	void push(int);
	void pop();
	ostream& print(ostream&);
private:
	vector<int> vec;
	int top;
};

inline void Stack::push(int i){
	int len=vec.size();
	//Do not use "top>=vec.size()-1". It is always ture.
	//You must convert size_type to int!
	//Attention: when you compare two things, you had better \
	convert them to the same type.
	if (top>=len-1){
		cerr<<"Vector overflows."<<endl;
		return;
	}
	top++;
	vec[top]=i;
} 
inline void Stack::pop(){
	if (top<0){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	top--;
}
ostream& Stack::print(ostream& os=cout){
	for (auto i=0;i<=top;i++)
		os<<vec[i]<<" ";
	os<<endl;
	return os;
}

int main(int argc,char** argv){
	vector<int> v(10,0);
	Stack test(v);
	test.push(10);
	test.push(20);
	test.print(cout);
	test.pop();
	return 0;
}

  队列

#include<iostream>
#include<vector>

using namespace std;

struct Queue{
public:
	Queue(vector<int> v):vec(v),head(0),tail(0){}
	void enqueue(const int&);
	void dequeue();
	ostream& print(ostream&);
private:
	vector<int> vec;
	int head,tail;
};

inline void Queue::enqueue(const int& i){
	int len=vec.size();
	if (tail==head-1||tail==len+head-1){
		cerr<<"Vector overflows."<<endl;
		return;
	}
	vec[tail]=i;
	if (tail<len-1)
		tail++;
	else 
		tail=0;
}
inline void Queue::dequeue(){
	int len=vec.size();
	if (tail==head){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	vec[head]=-9999;
	if (head<len){
		head++;
	}else {
		head=0;
	}
}
ostream& Queue::print(ostream& os=cout){
	for (auto beg=vec.begin();beg!=vec.end();beg++){
		cout<<*beg<<" ";
	}
	cout<<endl;
	return os;
}

int main(int argc,char** argv){
	vector<int> v(10,0);
	Queue test(v);
	test.enqueue(3);
	test.enqueue(4);
	test.print();
	test.dequeue();
	test.print();
	return 0;
}
练习10.1-1

  其过程如下:
  4| | | | |  → \rightarrow 4|1| | | |  → \rightarrow 4|1|3| | |  → \rightarrow
  4|1| | | |  → \rightarrow 4|1|8| | |  → \rightarrow 4|1| | | | 

练习10.1-2

  若A是存储两个栈的数组,将两个栈的栈头位置,一个放在A[1]处,一个放在A[n]处,前一个栈的函数和前面一致,后面的函数存储方向相反即可。

#include<iostream>
#include<vector>

using namespace std;

struct Stack{
public:
	Stack(vector<int> v):vec(v),top(-1),top_inv(v.size()){}
	void push(const int&);
	void pop();
	void push_inv(const int&);
	void pop_inv();
	ostream& print_plu(ostream&);
private:
	vector<int> vec;
	int top;
	int top_inv;
};

inline void Stack::push(const int& i){
	int len=vec.size();
	if (top>=top_inv-1){
		cerr<<"Vector overflows."<<endl;
		return;
	}
	top++;
	vec[top]=i;
} 
inline void Stack::pop(){
	if (top<0){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	top--;
}
inline void Stack::push_inv(const int&i){
	if (top>=top_inv-1){
		cerr<<"Vector overflows."<<endl;
		return;
	}
	top_inv--;
	vec[top_inv]=i;
} 
inline void Stack::pop_inv(){
	int len=vec.size();
	if (top_inv>len-1){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	top_inv++;
}
ostream& Stack::print_plu(ostream& os=cout){
	os<<"Stack1: ";
	for (int i=0;i<=top;i++)
		os<<vec[i]<<' ';
	os<<endl;
	os<<"Stack2: ";
	for (int i=vec.size()-1;i>=top_inv;i--)
		os<<vec[i]<<' ';
	os<<endl;
	return os;
}

int main(int argc,char** argv){
	vector<int> v(10,0);
	Stack test(v);
	test.push(10);
	test.push(20);
	test.push_inv(2);
	test.push_inv(3);
	test.print_plu(cout);
	test.pop();
	test.pop_inv();
	test.print_plu(cout);
	return 0;
}
练习10.1-3

  其过程如下:
  4| | | | |  → \rightarrow 4|1| | | |  → \rightarrow 4|1|3| | |  → \rightarrow
   |1|3| | |  → \rightarrow  |1|3|8| |  → \rightarrow  | |3|8| | 

练习10.1-4

  见上面程序,略

练习10.1-5
#include<iostream>
#include<vector>

using namespace std;

struct Deque{
public:
	Deque(vector<int> v):vec(v),head(0),tail(0){}
	void enqueue(const int&);
	void dequeue();
	void enqueue_inv(const int&);
	void dequeue_inv();
	ostream& print(ostream&);
private:
	vector<int> vec;
	int head,tail;
};

inline void Deque::enqueue(const int& i){
	int len=vec.size();
	if (tail==head-1||tail==len+head-1){
		cerr<<"Vector overflows."<<endl;
		return;
	}
	vec[tail]=i;
	if (tail<len-1)
		tail++;
	else 
		tail=0;
}
inline void Deque::enqueue_inv(const int& i){
	int len=vec.size();
	if (tail==head-1||tail==len+head-1){
		cerr<<"Vector overflows."<<endl;
		return;
	}
	if (head>0){
		head--;
		vec[head]=i;
	}
	else {
		head=len-1;
		vec[head]=i;
	}
}
inline void Deque::dequeue(){
	int len=vec.size();
	if (tail==head){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	vec[head]=-9999;
	if (head<len){
		head++;
	}else {
		head=0;
	}
}
inline void Deque::dequeue_inv(){
	int len=vec.size();
	if (tail==head){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	tail--;
	if (tail>=0){
		vec[tail]=-9999;
	}else {
		tail=len-1;
		vec[tail]=-9999;
	}
}
ostream& Deque::print(ostream& os=cout){
	for (auto beg=vec.begin();beg!=vec.end();beg++){
		cout<<*beg<<" ";
	}
	cout<<endl;
	return os;
}
int main(int argc,char** argv){
	vector<int> v(10,0);
	Deque test(v);
	test.enqueue(3);
	test.enqueue(4);
	test.enqueue_inv(1);
	test.enqueue_inv(2);
	test.print();
	test.dequeue();
	test.print();
	test.dequeue_inv();
	test.print();
	return 0;
}
练习10.1-6

  用两个堆,一个正向堆Stk2Que::stack1只运行函数push(),一个反向堆Stk2Que::stack2只运行函数pop(),然后为了使得能像队列一样环绕,注意加判断条件。然后注意一些细节问题,已经写到注释里面了。注意Stk2Que中stack的函数和queue的函数的边界条件的转换。

#include<iostream>
#include<vector>

using namespace std;

struct Stack{
	Stack(vector<int>& v):vec(v),top(-1),top_inv(0){}
	//Stack(vector<int> v,int i):vec(v),top(i){}
	void push(const int&);
	void pop_inv();
	ostream& print(ostream&);
	vector<int>& vec;
	//Stk2Que::stack1,stack2 must use the same vector!
	int top,top_inv;
};

inline void Stack::push(const int& i){
	int len=vec.size();
	if (top>=len-1){
		cerr<<"Vector overflows."<<endl;
		return;
	}
	top++;
	vec[top]=i;
} 
inline void Stack::pop_inv(){
	int len=vec.size();
	if (top_inv>len-1){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	vec[top_inv]=-9999;
	top_inv++;
}
ostream& Stack::print(ostream& os=cout){
	for (auto beg=vec.begin();beg!=vec.end();beg++){
		cout<<*beg<<" ";
	}
	cout<<endl;
	return os;
}

struct Stk2Que:public Stack{
	Stk2Que(vector<int>& v):Stack(v),stack1(v),stack2(v){}
	//Attention for constructor of inheritance class.
	//"Stk2Que(vector<int>v):stack1(v){}" can't cast vector<int> into 
	//\Stack 
	//"vector<int>" must add '&'!
	void enqueue(const int& i);
	void dequeue();
	ostream& print(ostream&);
private:
	Stack stack1;
	Stack stack2;
};

inline void Stk2Que::enqueue(const int& i){
	int len=stack2.vec.size();
	if (stack2.top+1==stack1.top_inv-1||stack2.top+1==len+stack1.top_inv-1){
		//Stk2Que::stack2.top+1==Queue::tail
		//Stk2Que::stack1.top_inv==Queue::head
		cerr<<"Vector overflows."<<endl;
		return;
	}
	if (stack2.top>=len-1){
		stack2.top=-1;
		stack2.push(i);
	}else
		stack2.push(i);
}
inline void Stk2Que::dequeue(){
	int len=stack1.vec.size();
	if (stack2.top+1==stack1.top_inv){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	if (stack1.top_inv>len-1){
		stack1.top_inv=0;
		stack1.pop_inv();
	}else
		stack1.pop_inv();
}
ostream& Stk2Que::print(ostream& os=cout){
	return stack1.print(os);
}

int main(int argc,char** argv){
	vector<int> v(10,0);
	Stk2Que test(v);
	test.enqueue(10);
	test.enqueue(20);
	test.print(cout);
	test.dequeue();
	test.print(cout);
}

  队列的运行时间和前面的队列的运行时间是同一时间复杂度的。

练习10.1_7

  两个队列,一个只运行enqueue();一个只运行dequeue();

#include<iostream>
#include<vector>

using namespace std;

struct Queue{
	Queue(vector<int>& v):vec(v),head(0),tail(0){}
	void enqueue(const int&);
	void dequeue();
	ostream& print(ostream&);
	vector<int>& vec;
	int head,tail;
};

inline void Queue::enqueue(const int& i){
	int len=vec.size();
	if (tail==head-1||tail==len+head-1){
		cerr<<"Vector overflows."<<endl;
		return;
	}
	vec[tail]=i;
	if (tail<len-1)
		tail++;
	else 
		tail=0;
}
inline void Queue::dequeue(){
	int len=vec.size();
	if (tail==head){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	vec[head]=-9999;
	if (head<len){
		head++;
	}else {
		head=0;
	}
}
ostream& Queue::print(ostream& os=cout){
	for (auto beg=vec.begin();beg!=vec.end();beg++){
		cout<<*beg<<" ";
	}
	cout<<endl;
	return os;
}

struct Que2Stk:private Queue{
public:
	Que2Stk(vector<int>& v):Queue(v),queue1(v),queue2(v),top(-1){}
	void push(const int& i);
	void pop();
	ostream& print(ostream&); 
private:
	Queue queue1,queue2;
	int top;
};

inline void Que2Stk::push(const int& i){
	int len=queue1.vec.size();
	if (top>=len-1){
		cerr<<"Vector overflows."<<endl;
		return;
	}
	top++;
	queue1.tail=top;
	queue1.enqueue(i);
}
inline void Que2Stk::pop(){
	if (top<0){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	queue2.head=top;
	queue2.dequeue();
	top--;
}
ostream& Que2Stk::print(ostream& os){
	return queue1.print(os);
}

int main(int argc,char** argv){
	vector<int> v(10,0);
	Que2Stk test(v);
	test.push(10);
	test.push(20);
	test.print(cout);
	test.pop();
	test.print(cout);
}

  上述运行时间和前面的栈的运行时间是同一时间复杂度的。

10.2链表

//"LinkedList.h"
#include<iostream>
#include<vector>

using namespace std;

struct List{
	List(int k):key(k),next(NULL),prev(NULL){}
	int key;
	List *next,*prev;
};

struct LinkedList:public List{
	LinkedList(List& k):List(k),temp(k){head=&temp;}
	List* search(const int& k);
	void Insert(List&);
	void Delete(List&);
	void Delete(const int&);
	ostream& print(ostream&);
	void view();
	List& temp;
	List* head;
};

inline List* LinkedList::search(const int& k){
	List* x=head;
	while ((x!=NULL)&&((x->key)!=k))
		x=x->next;
	if (x==NULL)
		cerr<<"Not find "<<k<<endl;	
	return x;
}
inline void LinkedList::Insert(List& listX){
	List* x=&listX;
	x->next=head;
	if(head!=NULL)
		head->prev=x;
	head=x;
	x->prev=NULL;
}
inline void LinkedList::Delete(List& listX){
	List* x=&listX;
	if (x->prev!=NULL)
		x->prev->next=x->next;
	else
		head=x->next;
	if (x->next!=NULL)
		x->next->prev=x->prev;
}
inline void LinkedList::Delete(const int& listX){
	List* x=search(listX);
	if (x->prev!=NULL)
		x->prev->next=x->next;
	else
		head=x->next;
	if (x->next!=NULL)
		x->next->prev=x->prev;
}
ostream& LinkedList::print(ostream& os=cout){
	auto x=this->head;
	while(x!=NULL){
		os<<(x->key)<<" ";
		x=x->next;
	}
	cout<<endl;
	return os;
}
#include"LinkedList.h"

int main(int argc,char** argv){
	List a(10),b(20);
	LinkedList test(a);
	test.Insert(b);
	test.print();
	test.Delete(20);
	test.print();
}

  带哨兵

//LinkedListSentinel.h"
#include<iostream>
#include<vector>

using namespace std;

struct List{
	List()=default;
	List(int k):key(k){}
	int key=0;
	List *next=NULL,*prev=NULL;
};

struct LinkedList:public List{
	LinkedList(List& k):nil(&NIL){
		nil->next=&k;
		nil->prev=&k;
		k.next=nil;
		k.prev=nil;
	}
	List* search(const int& k);
	void Insert(List&);
	void Delete(List&);
	void Delete(const int&);
	ostream& print(ostream&);
	List NIL;
	List* nil;
};

inline List* LinkedList::search(const int& k){
	List* x=nil->next;
	while (x!=NULL&&x->key!=k)
		x=x->next;
	if (x==NULL)
		cerr<<"Not find "<<k<<endl;	
	return x;
}
inline void LinkedList::Insert(List& listX){
	List* x=&listX;
	x->next=nil->next;
	if(nil->next!=NULL)
		nil->next->prev=x;
	nil->next=x;
	x->prev=NULL;
}
inline void LinkedList::Delete(List& listX){
	List* x=&listX;
	if (x->prev!=NULL)
		x->prev->next=x->next;
	else
		nil->next=x->next;
	if (x->next!=NULL)
		x->next->prev=x->prev;
}
inline void LinkedList::Delete(const int& listX){
	List* x=search(listX);
	return Delete(*x);
}
ostream& LinkedList::print(ostream& os=cout){
	List* x=nil->next;
	while(x!=nil){
		os<<(x->key)<<" ";
		x=x->next;
	}
	cout<<endl;
	return os;
}
#include"LinkedListSentinel.h"
int main(int argc,char** argv){
	List a(10),b(20);
	LinkedList test(a);
	test.Insert(b);
	test.print();
	test.Delete(a);
	test.print();
	test.Delete(*(test.nil->prev));
	test.print();
}
练习10.2-1

  INSERT在单链表是可以在 O ( 1 ) O(1) O(1)内完成的。DELETE是需要 O ( n ) O(n) O(n)才能完成。

练习10.2-2

  要用到上面List类和LinkedList类及其相关成员函数。

#include<iostream>
#include<vector>
#include"LinkedList.h"

using namespace std;
struct Lik2Stk:public LinkedList
{
	Lik2Stk(LinkedList l):LinkedList(l),L(l),top(-1){}
	void push(List&);
	void pop();
	ostream& print(ostream&);
	LinkedList L;
	int top;
};

void Lik2Stk::push(List& X){
	top++;
	L.Insert(X);
}
void Lik2Stk::pop(){
	if(top<0){
		cerr<<"Vector underflows."<<endl;
		return;
	}
	top--;
	L.Delete(*(L.head));
}
ostream& Lik2Stk::print(ostream& os=cout){
	return L.print(os);
}

int main(int argc,char** argv){
	List a(30),b(20);
	LinkedList A(a);
	Lik2Stk test(A);
	test.push(b);
	test.print();
	test.pop();
	test.print();
}
练习10.2-3

  在上面的LinkedList类的基础上(List类只用next指针下,即单链表),我是没有想到怎么能只用单链表在 O ( 1 ) O(1) O(1)的复杂度下实现dequeue的。如果是单链表,从head到dequeue()需要去掉的元素(即最先进入链表的元素),需要进行n-1次next操作。只有双链表能在 O ( 1 ) O(1) O(1)内实现dequeue()和enqueue()的操作。在这里使用带nil的链表,其的程序在前面已经展示了,就不贴过来了。

#include<iostream>
#include<vector>
#include"LinkedListSentinel.h"

using namespace std;
struct Lik2Que{
	Lik2Que(List& l):list(l),L(list){}
	void enqueue(List&);
	void dequeue();
	ostream& print(ostream&);
	int head=0,tail=0;
	List& list;
	LinkedList L;
};
void Lik2Que::enqueue(List& x){
	L.Insert(x);
	tail++;
}
void Lik2Que::dequeue(){
	if (head==tail){
		cout<<"The queue underflows."<<endl;
		return;
	}
	L.Delete(*(L.nil->prev));
	head++;
}
ostream& Lik2Que::print(ostream& os=cout){
	return L.print(os);
}

int main(int argc,char** argv){
	List a(10),b(20);
	Lik2Que test(a);
	test.enqueue(b);
	test.print();
	test.dequeue();
	test.print();
}
练习10.2-4

   只要将nil的key值赋值为输入k既可。

inline List* LinkedList::search(const int& k){
	List* x=nil->next;
	nil->key=k;
	while (x->key!=k)
		x=x->next;
	if (x==nil)
		cerr<<"Not find "<<k<<endl;	
	return x;
}
练习10.2-5
#include<iostream>
#include<vector>

using namespace std;

struct List{
	List()=default;
	List(int k):key(k){}
	int key=0;
	List *next=NULL,*prev=NULL;
};

struct LinkedList:public List{
	LinkedList(List& k):nil(&NIL){
		nil->next=&k;
		nil->prev=&k;
		k.next=nil;
		k.prev=nil;
	}
	List* search(const int& );
	List* search(const int& ,int&);
	void Insert(List&);
	void Delete(int);
	ostream& print(ostream&);
	List NIL;
	List* nil;
};

inline List* LinkedList::search(const int& k,int& pos){
	List* x=nil->next;
	nil->key=k;
	while (x->key!=k){
		x=x->next;
		pos++;
	}
	if (x==nil)
		cerr<<"Not find "<<k<<endl;	
	return x;
}
inline List* LinkedList::search(const int& k){
	int ignoreThisParameter=0;
	return search(k,ignoreThisParameter);
}
inline void LinkedList::Insert(List& listX){
	List* x=&listX;
	x->next=nil->next;
	nil->next=x;
}
inline void LinkedList::Delete(int listX){
	int pos=0;
	List* x=search(listX,pos);
	auto y=nil;
	for (int i=0;i<pos;i++)
		y=y->next;
	y->next=x->next;
}
ostream& LinkedList::print(ostream& os=cout){
	List* x=nil->next;
	while(x!=nil){
		os<<(x->key)<<" ";
		x=x->next;
	}
	cout<<endl;
	return os;
}

int main(int argc,char** argv){
	List a(10),b(20);
	LinkedList test(a);
	test.Insert(b);
	test.print();
	test.Delete(20);
	test.print();
}

  各函数的运行时间:
  search()的运行时间和前面的运行时间是一致的,为 Θ ( n ) \Theta (n) Θ(n)
  Insert()的运行时间也和前面的运行时间一致,为 Θ ( 1 ) \Theta (1) Θ(1)
  Delete()的运行时间为 Θ ( n ) \Theta (n) Θ(n)

练习10.2-6
#include<iostream>
#include<vector>

using namespace std;

struct List{
	List()=default;
	List(int k):key(k){}
	int key=0;
	List *next=NULL,*prev=NULL;
};

struct LinkedList:public List{
	LinkedList(List& k):nil(&NIL){
		nil->next=&k;
		nil->prev=&k;
		k.next=nil;
		k.prev=nil;
	}
	LinkedList(List* k):nil(&NIL){
		nil->next=k;
		nil->prev=k;
		k->next=nil;
		k->prev=nil;
	}
	List* search(const int& k);
	void Insert(List&);
	void Delete(List&);
	void Delete(const int&);
	ostream& print(ostream&);
	List NIL;
	List* nil;
};

inline List* LinkedList::search(const int& k){
	List* x=nil->next;
	while (x!=NULL&&x->key!=k)
		x=x->next;
	if (x==NULL)
		cerr<<"Not find "<<k<<endl;	
	return x;
}
inline void LinkedList::Insert(List& listX){
	List* x=&listX;
	x->next=nil->next;
	if(nil->next!=NULL)
		nil->next->prev=x;
	nil->next=x;
	x->prev=nil;
}
inline void LinkedList::Delete(List& listX){
	List* x=&listX;
	if (x->prev!=NULL)
		x->prev->next=x->next;
	else
		nil->next=x->next;
	if (x->next!=NULL)
		x->next->prev=x->prev;
}
inline void LinkedList::Delete(const int& listX){
	List* x=search(listX);
	return Delete(*x);
}
ostream& LinkedList::print(ostream& os=cout){
	List* x=nil->next;
	while(x!=nil){
		os<<(x->key)<<" ";
		x=x->next;
	}
	cout<<endl;
	return os;
}
void Union(LinkedList l1,LinkedList l2){
	l2.nil->next->prev=l1.nil->prev;
	l1.nil->prev->next=l2.nil->next;
	l2.nil->prev->next=l1.nil;
	l1.nil->prev=l2.nil->prev;
}

int main(int argc,char** argv){
	List* a=new List(10);
	LinkedList test(a);
	List* b=new List(20);
	LinkedList test2(*b);
	Union(test,test2);
	test.print();
}
练习10.2-7
#include<iostream>
#include<vector>

using namespace std;

struct List{
	List()=default;
	List(int k):key(k){}
	int key=0;
	List *next=NULL,*prev=NULL;
};

struct LinkedList:public List{
	LinkedList(List& k):nil(&NIL){
		nil->next=&k;
		nil->prev=&k;
		k.next=nil;
		k.prev=nil;
	}
	List* search(const int& );
	List* search(const int& ,int&);
	void Insert(List&);
	void Delete(int);
	void Inverse();
	ostream& print(ostream&);
	List NIL;
	List* nil;
};

inline List* LinkedList::search(const int& k,int& pos){
	List* x=nil->next;
	nil->key=k;
	while (x->key!=k){
		x=x->next;
		pos++;
	}
	if (x==nil)
		cerr<<"Not find "<<k<<endl;	
	return x;
}
inline List* LinkedList::search(const int& k){
	int ignoreThisParameter=0;
	return search(k,ignoreThisParameter);
}
inline void LinkedList::Insert(List& listX){
	List* x=&listX;
	x->next=nil->next;
	nil->next=x;
}
inline void LinkedList::Delete(int listX){
	int pos=0;
	List* x=search(listX,pos);
	auto y=nil;
	for (int i=0;i<pos;i++)
		y=y->next;
	y->next=x->next;
}
ostream& LinkedList::print(ostream& os=cout){
	List* x=nil->next;
	while(x!=nil){
		os<<(x->key)<<" ";
		x=x->next;
	}
	cout<<endl;
	return os;
}
void LinkedList::Inverse(){
	List* temp1=nil;
	List* x=nil->next;
	while (x!=nil){
		auto temp2=*x;
		x->next=temp1;
		temp1=x;
		x=temp2.next;
	}
	nil->next=temp1;
}

int main(int argc,char** argv){
	List a(10),b(20);
	LinkedList test(a);
	test.Insert(b);
	test.print();
	test.Inverse();
	test.print();
}
练习10.2-8

  这个问题应该的做法应该是next和prev地址取xor然后根据改变0,1的位置,得到对应改变地址的数据。然后根据头(head)地址和改变地址的数据,就能得到list中一个元素的next和prev。具体可以用表示为:
e l e m e n t . n p = x o r ( e l e m e n t . p r e v , e l e m e n t . n e x t ) element.np=xor(element.prev,element.next) element.np=xor(element.prev,element.next)
e l e m e n t . n e x t = e l m e n t . p r e v + C o u n t G a p ( e l e m e n t . n p ) × G a p element.next=elment.prev+CountGap(element.np)\times Gap element.next=elment.prev+CountGap(element.np)×Gap
e l m e n t . p r e v = e l e m e n t . n e x t − C o u n t G a p ( e l e m e n t . n p ) × G a p elment.prev=element.next-CountGap(element.np)\times Gap elment.prev=element.nextCountGap(element.np)×Gap
  所以只要知道list中head的地址和储存在每个元素中的 n p np np值就可以实现双向链表了。如果要逆转的话就是把加号和减号互换就行,运行时间也是 Θ ( 1 ) \Theta (1) Θ(1)
  在C++让地址取异或挺麻烦的。所以我直接取的是地址的差值,其实也是等价于 C o u n t G a p ( e l e m e n t . n p ) × G a p CountGap(element.np)\times Gap CountGap(element.np)×Gap
  这个题目做起来挺麻烦的,主要是对于一个元素 A 1 A_1 A1,要得到他的下一个元素 A 2 A_2 A2,要用到 A 1 . n p A_1.np A1.np和上一个元素 A 0 A_0 A0的地址,而你又不能只用 A 1 A_1 A1的条件去得到 A 2 A_2 A2,要找到 A 2 A_2 A2不仅要分奇偶讨论还有一堆的边界条件讨论。下面程序在只用np值下只完成了list的基本操作search()insert()delete();逆转的方法和我前面提到的是一样的,只不过要改边界条件,比较繁琐,大家有兴趣自己改下吧。
  程序中的TAIL,HEAD,tail,head,(后两个是前面对应指针)只是为了简化边界条件引出来的,如果想要更简单点,可以考虑用8个(不要指针的话4个,分别是奇数头尾,偶数头尾)。

#include<iostream>
#include<vector>

using namespace std;

struct List{
	List()=default;
	List(int k):key(k){}
	int key=0;
	int thisElement_Former=0,thisElement_Latter=0;
	int long np=thisElement_Former-thisElement_Latter;
};

struct LinkedList:public List{
	LinkedList(List& k){head=&HEAD;tail=tail;HEAD.np=tail-head;
		tail->np=HEAD.np;Insert(k);}
	List* search(const int&);
	List* next(List*);
	List* prev(List*);
	void Insert(List&);
	void Delete(List&);
	ostream& print(ostream&);
	List HEAD,TAIL;
	List* head,*tail;
};
List* LinkedList::prev(List* listX){
	int pos=1;
	List* odd=head+head->np;
	List* even=head;
	List* x=odd;
	while (x!=tail){
		if(pos%2==1){
			auto temp=even;
			if (x!=listX){
				x=even+x->np;
				even=x;
				pos++;
			}else{
				return temp;
			}
		}else{
			auto temp=odd;
			if (x!=listX){
				x=odd+x->np;
				odd=x;
				pos++;
			}else{
				return temp;
			}
		}
	}
	if (x==tail)
		return (tail-tail->np);
}
List* LinkedList::next(List* listX){
	int pos=1;
	List* odd=head+head->np;
	List* even=head;
	List* x=odd;
	while (x!=tail){
		if(pos%2==1){
			auto temp=even;
			if (x!=listX){
				x=even+x->np;
				even=x;
				pos++;
			}else{
				return (temp+x->np);
			}
		}else{
			auto temp=odd;
			if (x!=listX){
				x=odd+x->np;
				odd=x;
				pos++;
			}else{
				return (temp+x->np);
			}
		}
	}
}
inline List* LinkedList::search(const int& k){
	List* x=head+head->np;
	while (x->key!=k&&x!=tail)
		x=next(x);
	return x;
}

inline void LinkedList::Insert(List& listX){
	List* newFirstElement=&listX;
	newFirstElement->np=head->np;
	auto oldFirstElement=head+head->np;
	oldFirstElement->np=(head+oldFirstElement->np)-newFirstElement;
	head->np=newFirstElement-head;
}
inline void LinkedList::Delete(List& listX){
	List* x=search(listX.key);
	if (x==head+head->np&&next(x)!=tail){
		next(x)->np=next(next(x))-prev(x);
		head->np=x->np;
	}else if (x==head+head->np&&next(x)==tail){
		tail->np=head->np;
		head->np=x->np;
	}else if (x!=head+head->np&&next(x)==tail){
		auto j=next(x)-prev(prev(x));
		tail->np=tail-prev(x);
		prev(x)->np=j;
	}else{
		auto i=next(next(x))-prev(x);
		auto j=next(x)-prev(prev(x));
		next(x)->np=i;
		prev(x)->np=j;
	}
}
ostream& LinkedList::print(ostream& os=cout){
	auto x=head+head->np;
	while (x!=tail){
		cout<<x->key<<" ";
		x=next(x);
	}
	cout<<endl;
	return os;
}

int main(int argc,char** argv){
	List a(10),b(20),c(30);
	LinkedList test(a);
	test.Insert(b);
	test.Insert(c);
	test.print();
	test.Delete(a);
	test.print();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值