实现双向循环,具有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;
}
C++双向循环链表
最新推荐文章于 2022-09-22 15:27:33 发布