C++双向循环链表

                                   实现双向循环,具有chain类的所有功能

动态链表的实现十分简单。它的好处在于动态分配内存空间,有效避免了各种问题,同时通过插入链表可以实现插入排序,也就是说,当你把新的数据输入时,数据所在的位置已经是按顺序排好的了,在输出时,只要遍历链表就可以了,用双向循环链表实现的好处在于能够按两种顺序(从大到小,从小到大)对链表进行遍历,实现起来相当方便。

//DoubleCircular.h
#include<iostream>
#include"xcept.h"
using namespace std;

template<class T>
class DoubleCircular;
template<class T>
class DoubleNode{
 friend class DoubleCircular<T>;
  private:
   T data;
   DoubleNode<T> *left  ,*right;
};

template<class T>
class DoubleCircular {
   public:
      DoubleCircular() {rightEnd = 0;} //构造函数
     ~DoubleCircular(); //析构函数
      bool IsEmpty() const {return rightEnd == 0;} //如果表为空则返回true,否则返回false
      int Length() const; //返回表的大小 
      bool Find(int k, T& x) const; //寻找表中第k个元素,并把它保存到x中;如果不存在,则返回false
      int Search(const T& x) const; //返回元素x在表中的位置;如果x不在表中,则返回0
      DoubleCircular<T>& Delete(int k, T& x); //删除表中第k个元素,并把它保存到x中,函数返回修改后的线性表
      DoubleCircular<T>& Insert(int k, const T& x); //在第k个元素之后插入x,函数返回修改后的线性表
      void Output(ostream& out) const; //把线性表放入输出流out之中
   private:
      DoubleNode<T>  *rightEnd; //指向最右端节点的指针
}; 
template<class T>
DoubleCircular<T>::~DoubleCircular()
{
   if (!rightEnd) return; // 链表为空

   DoubleNode<T> *current =rightEnd->left,
                 *next; //声明当前指针指向最右端节点的左以及下一个指针next       
   while (current !=rightEnd) {
      next = current->left;//下一指针指向当前指针的左端
      delete current;//释放掉当前指针
      current = next;//当前指针指向下一指针
      }
   delete rightEnd;//释放掉最右端指针
}
template<class T>
int DoubleCircular<T>::Length() const
{
 int len = 0;//初始化len为0
   if (!rightEnd) return 0;  //链表为空
   DoubleNode<T> *current =rightEnd->left;//当前指针指向最右端节点的左
   while (current != rightEnd) {
     current = current->left;//下一指针指向当前指针的左端
  len++;//len后加加
   }
   len++;  // for last node
   return len;
}
template<class T>
bool DoubleCircular<T>::Find(int k, T& x) const//寻找表中第k个元素,并把它保存到x中;如果不存在,则返回false
{
   if (k < 1 || !rightEnd) return false;//k无意义或者链表为空
   DoubleNode<T> *current = rightEnd->left;//当前指针指向最右端节点的左
   int index = 1;//标记下标为1 
   while (index < k && current !=rightEnd) {
      current = current->left;//下一指针指向当前指针的左端
      index++;//下标后加加
      }
   if (index==k)//当前元素即为第k个元素
   {x = current->data; return true;}
   return false; 
}
template<class T>
int DoubleCircular<T>::Search(const T& x) const//返回元素x在表中的位置;如果x不在表中,则返回0
{
   if (!rightEnd) return 0;  //链表为空
   DoubleNode<T> *current = rightEnd->left;//当前指针指向最右端节点的左
   int index = 1;//标记下标为1 
   while ( current != rightEnd&& current->data != x) //当当前指针不是最右端节点且指向的值与x的值不同时
   {
      current = current->left;//下一指针指向当前指针的左端
      index++; }
   if (current->data == x)//当当前指针指向的值与x的值相同时
    return index;
   return 0;
}
template<class T>
DoubleCircular<T>& DoubleCircular<T>::Delete(int k, T& x)//删除表中第k个元素,并把它保存到x中,函数返回修改后的线性表
{
   if (k<1||!rightEnd) throw OutOfBounds();//k无意义或者链表为空时抛出异常
   DoubleNode<T> *p =rightEnd->left;//p指针指向最右端节点的左
   int index = 1;//标记下标为1  
   for (; index<k && p!=rightEnd; index++)
      p = p->left;//p指向p的左
   if (index != k) throw OutOfBounds(); // 当下标与k不同时抛出异常
   //删除k
   p->left->right = p->right;
   p->right->left = p->left;
//
   x = p->data;//将p指向的数据赋值给x
   if (p == rightEnd)  //当p恰巧最右端节点时 
      if (k == 1)  // 新的表是空的
         rightEnd = 0;
      else // 不空
        rightEnd=rightEnd->right;//将最右端节点的右赋值给最右端节点
   delete p;//释放
   return *this;
}
template <class T>
DoubleCircular<T>& DoubleCircular<T>::Insert(int k, const T& x)//在第k个元素之后插入x,函数返回修改后的线性表
{
   if (k < 0) throw OutOfBounds();//k无意义时抛出异常
   if (k) {
      if (!rightEnd) throw OutOfBounds();  // 空表时抛出异常
      DoubleNode<T> *p =rightEnd->left;//p指针指向最右端节点的左
      int index = 1;//标记下标为1 
      for (; index < k && p != rightEnd;
             index++)  
         p = p->left;//p指向p的左
      if (index != k) throw OutOfBounds();// 当下标与k不同时抛出异常 
//在第k个元素后插入x
      DoubleNode<T> *y = new DoubleNode<T>;
      y->data = x;
      y->left = p->left;
      y->left->right = y;
      p->left = y;
      y->right = p;
      if (p ==rightEnd)
    rightEnd= y;
      }
   else {//作为第一个插入
         DoubleNode<T> *y = new DoubleNode<T>;
         y->data = x;
         if (rightEnd) {
            y->left = rightEnd->left;
            y->left->right = y;
           rightEnd->left = y;
            y->right = rightEnd;
            }
         else {//空表
               rightEnd= y;
               y->right = y;
               y->left = y;
               }
         }
   return *this;
}
//输出
template<class T>
void DoubleCircular<T>::Output(ostream& out) const
{
   if (!rightEnd) return;
   DoubleNode<T> *current;
   for (current = rightEnd->left; current != rightEnd;
                         current = current->left)
      out << current->data << "  ";
  out << current->data << "  ";
}
// 重载<<
template <class T>
ostream& operator<<(ostream& out, const DoubleCircular<T>& x)
   {x.Output(out); return out;}

 

//DoubleCircle.cpp
#include<iostream>
#include"DoubleCircular.h"
using namespace std;

void main(void)
{
      DoubleCircular<int> L;
      cout << "Length = " << L.Length() << endl;
      cout << "IsEmpty = " << L.IsEmpty() << endl;
   L.Insert(0,4).Insert(1,5).Insert(2,1).Insert(3,3).Insert(4,9).Insert(5,7);
   L.Insert(1,6).Insert(3,8).Insert(5,2);
      cout << "新建的链表为 " << L << endl;
   cout<<"Length = "<<L.Length()<<endl;
      cout << "IsEmpty = " << L.IsEmpty() << endl;
   cout<<"链表中值为3的位置: "<<L.Search(3)<<endl;
      int z;
   //
      L.Find(3,z);
      cout << "第三个元素为:" << z << endl;
   //
      cout << "9的位置为:" << L.Search(9) << endl;
   //
     
   int a1,a2,a3;
   L.Delete(5,a1).Delete(1,a2).Delete(3,a3);
      cout << "删除的元素是: " << a1
           << "  " << a2 << "  " << a3 << endl;
      cout << "新的链表为 :" << L << endl;
      L.Delete(1,a1).Delete(1,a2);
      cout << "删除的元素是:" << a1
           << "  " << a2 << endl;
      cout << "新的链表为: " << L << endl;
  
}
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值