基于单链表的循环链表以及双链表的实现

1、循环链表

在很多实际问题中,操作是在首或者尾部进行,此时单链表的头节点就显得不够方便,如果改用终端端点的尾指针,并且该尾部指针指向头节点,则查找头节点,开始节点以及尾部节点都很方便,他们的存储地址:rear->next,rear->next->next.rear。这就是循环链表:

//clinklist
 template<typename T>
 class clinklist{
 private:
	 node<T>*rear;
	 node<T>*first;
	 int size;
 public:
	 clinklist(){first=new node<T>;rear->next=first;first->next=first;size=0;}
     clinklist(T a[],int n);
 ~clinklist();
 int getsize();
 T get(int i);
 int loc(T x);
 void insert(int i,T x);
 T del(int i);
 void prt();};
 template<typename T>
 clinklist<T>::clinklist(T a[],int n){
	 first=new node<T>;
  node<T>*p=first;
 for(int i=0;i<n;i++)
 {node<T>*s=new node<T>;
 s->data=a[i];
 p->next=s;
 p=s;}
 size=n;
 rear=p;
 p->next=first;
}
 template<typename T>
 int clinklist<T>::getsize(){
 return size;}
 template<typename T>
 T clinklist<T>::get(int i){
	 node<T>*p=first;
 int j=0;
 while(p!=rear&&j<i){
	 p=p->next;
 j++;}
 if(p==rear)throw"i error";
 else return p->data;}
 template<typename T>
 int clinklist<T>::loc(T x){
	 node<T>*p=rear->next;//rear->next==first
 int j=0;
 while(p!=rear&&p->data!=x){
	 p=p->next;
 j++;}
 if(p==rear)return -1;
 else return j;}
 template<typename T>
 void clinklist<T>::insert(int i,T x){
	 node<T>*p=rear->next;
 int j=0;
 while(p!=rear&&j<i-1){
	 p=p->next;
 j++;}
 if(p==rear)cout<<"i error";
 else {
 node<T>*s=new node<T>;
 s->data=x;
 s->next=p->next;
 p->next=s;
 size++;}
 }
 template<typename T>
 T clinklist<T>::del(int i){
	 node<T>*p=rear->next;
 int j=0;
 while(p!=rear&&j<i-1){
	 p=p->next;
 j++;}
 if(p==rear||p->next==rear)throw"del error";
 else{node<T>*q=p->next;
 T x=q->data;
 p->next=q->next;
 delete q;
 size--;
 return x;}
 }
 template<typename T>
 clinklist<T>::~clinklist(){
	 node<T>*p=rear->next;
	 while(p!=rear){
	 node<T>*q=p;
	 p=p->next;
	 delete q;}
 }
 template<typename T>
 void clinklist<T>::prt(){
	  node<T>*p=first;
  if(p==rear)cout<<"empty"<<endl;

  while(p!=rear){
	   p=p->next;
	  cout<<p->data<<" ";
	 }
 cout<<endl;}

2、双向链表

虽然循环链表以及很方便了,但是主要针对的是首尾端,对于其中任意一个节点比如前驱节点的扫描还是需要遍历整个循环链表,因此可以在单循环链表基础上再设置一个指向前驱的指针域。那么对于链表中开始,终端,中间任意位置处节点的操作都是相同:

 //dclinklist
 template<typename T>
 struct dnode{
 T data;
 dnode<T>*pri;
 dnode<T>*next;};
 template<typename T>
 class dclinklist{
 private:
 dnode<T>*rear;
dnode<T>*first;
int size; 
 public:
	 dclinklist(){first=new dnode<T>;first=rear->next;first->next=first;size=0;}
     dclinklist(T a[],int n);
    ~dclinklist();
 int getsize();
 T get(int i);
 int loc(T x);
 void insert(int i,T x);
 T del(int i);
 void prt();};
 template<typename T>
 dclinklist<T>::dclinklist(T a[],int n){
 first=new dnode<T>;
 dnode<T>*p=first;
 for(int i=0;i<n;i++)
 {dnode<T>*s=new dnode<T>;
 s->data=a[i];
 p->next=s;
 p=s;}
 size=n;
 rear=p;
 p->next=first;}
 template<typename T>
 dclinklist<T>::~dclinklist(){
	 dnode<T>*p=rear->next;
	 while(p!=rear){
	 dnode<T>*q=p;
	 p=p->next;
	 delete q;}
 }
 template<typename T>
 int dclinklist<T>::getsize(){
 return size;}
 template<typename T>
 T dclinklist<T>::get(int i){
	 dnode<T>*p=rear->next;
 int j=0;
 while(p!=rear&&j<i){
	 p=p->next;
 j++;}
 if(p==rear)throw"i error";
 else{return p->data;}}
 template<typename T>
 int dclinklist<T>::loc(T x){
 dnode<T>*p=first;
 int j=0;
 while(p!=rear&&p->data!=x){
	 p=p->next;
 j++;}
 if(p==rear)return -1;
 else return j;}
 template<typename T>
 void dclinklist<T>::insert(int i, T x){
 dnode<T>*p=first;
 int j=0;
 while(p!=rear&&j<i-1){
	 p=p->next;
 j++;}
 if(p==rear)cout<<"i error"<<endl;
 else{
 dnode<T>*s=new dnode<T>;
 s->data=x;
 s->pri=p;
 s->next=p->next;
 p->next->pri=s;
 p->next=s;
 size++;}
 }
 template<typename T>
 T dclinklist<T>::del(int i){
 dnode<T>*p=first;
 int j=0;
 while(p!=rear&&j<i-1){
	 p=p->next;
 j++;}
 if(p==rear||p->next==rear)throw"del error";
 else{dnode<T>*q=p->next;
 T x=q->data;
 ( q->pri)->next=q->next;
 (q->next)->pri=q->pri;
 delete q;
 size--;
 return x;}
 }
 template<typename T>
 void dclinklist<T>::prt(){
	  dnode<T>*p=first;
  if(p==rear)cout<<"empty"<<endl;

  while(p!=rear){
	   p=p->next;
	  cout<<p->data<<" ";
	 }
 cout<<endl;}

双循环链表同单循环链表比,求表长,查找等操作基本一样,唯一就是插入和删除不一样,它是一种对称结构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值