算法导论—第三部分
数据结构
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.next−CountGap(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();
}