📄 clist.cpp
字号:
#ifndef SCK_CLIST_CPP
#define SCK_CLIST_CPP
/////////////////////////////////////////////////////////////////////////////
// CList.cpp 双向链表类标准C++的声明及实现
// CopyRight(C) 1996,2008 TCSY 公司 圣诞节新版
// Pentium Working Room ShanChengKun 2003.12.24 更新
/////////////////////////////////////////////////////////////////////////////
#define EMPTY_NODE 0 // 空节点,Del()返回
#define START_NODE 1 // 首节点,Del()标志
#define MIDDLE_NODE 2 // 中节点,Del()返回
#define LAST_NODE 3 // 尾节点,Del()标志
template<class T> class CList; // 前置声明的CList类
//-------------------------------------------------------------------------//
// 自定义的通用链表节点类,T为简单数据类型
template<class T> // 链表节点指针
class CNode
{
friend class CList<T>; // 友元.CList类
long no; // 此节点的序号
T data; // 此节点的数据
CNode<T> *prior; // 前驱节点指针
CNode<T> *next; // 后继节点指针
public: // 不负责释放由前驱后继的节点指针所指向的内存
CNode() {no = -1; prior = next = NULL;} // 默认构造函数
CNode(T& dat) {no = -1; data = dat; prior = next = NULL;}
T GetData(void) {return data;} // 获取节点数据
void SetData(T& dat) {data = dat;} // 设置节点数据
};
//-------------------------------------------------------------------------//
// 自定义的通用链表类模板,T为简单数据类型
template<class T> // 数据双向搜索
class CList
{
long sum; // 所有节点总数
CNode<T> *start; // 首节点的指针
CNode<T> *last; // 尾节点的指针
CNode<T> *curr; // 当前位置指针
public: // 向链首走=向上(向前),向链尾走=向下(向后)
long Sum(void) {return sum;} // 所有节点总数
void Rewind(int w) {curr = (w ? last : start);} // 0链首,1链尾
T& operator()(void) {return curr->data;} // 引用当前节点
long GetNth(void) {return (curr ? curr->no : -1);}// 取当前序号
T& operator[](long nth) {Seek(nth - curr->no); return curr->data;}
CNode<T> *GetCurrPtr(void) {return curr;} // 获取当前指针
bool SetCurrPtr(CNode<T> *ptr)
{
if(!curr || !ptr) return false; // 设置当前指针
curr = ptr; return true;
}
bool Prev(void) // 移动到上一点
{
if(!curr || !curr->prior) return false;
curr = curr->prior; return true;
}
bool Next(void) // 移动到下一点
{
if(!curr || !curr->next) return false;
curr = curr->next; return true;
}
CList() {sum = 0; start = last = curr = NULL;} // 缺省构造函数
CList(CList<T>& list); // 拷贝构造函数
CList(T& dat) {sum = 0; start = last = curr = NULL; Add(dat);}
~CList() {Destroy();} // 默认析构函数
bool Add(T& dat); // 尾追加为当前
int Del(int bSort = 0); // 删当前指向下
bool Ins(T& dat, int bType, int bSort = 0); // 当前前后插入
void SortNo(void); // 上点号起重编
bool Seek(long num); // -首向、+尾向
void Destroy(void) {Rewind(1); while(Del());} // 释放链表节点
CList<T>& operator = (CList<T>& list); // 重置为一新链
CList<T>& operator = (T& dat); // 重置为单节点
CList<T>& operator += (CList<T>& list); // 尾部追加新链
CList<T>& operator += (T& dat); // 尾部追加节点
// 链表相加操作函数、右加节点操作函数、左加节点操作函数
friend CList<T> operator + (CList<T>& list1, CList<T>& list2);
friend CList<T> operator + (CList<T>& list, T& dat);
friend CList<T> operator + (T& dat, CList<T>& list);
};
//-------------------------------------------------------------------------//
// 链表类的复制拷贝构造函数(此函数必须准确无误)
template<class T>
CList<T>::CList(CList<T>& list)
{
sum = 0; start = last = curr = NULL; // 注意这很重要
if(!list.Sum()) return; // 不拷贝空链表
list.Rewind(0); // 返回到链首点
do {if(!Add(list())) break;} while(list.Next());// 遍历整个链表
}
// 在尾部追加一个数据节点
template<class T>
bool CList<T>::Add(T& dat)
{
CNode<T> *info = new CNode<T>(dat); // 申请拷贝空间
if(!info) return false;
info->no = sum++; // 置序号总数增
if(last) {info->prior = last; last->next = info; last = curr = info;}
else start = last = curr = info; return true; // 尾加载新节点
}
// 删除(空0、首1、中2、尾3)节点,默认不重排序号
template<class T>
int CList<T>::Del(int bSort)
{
if(!curr) return EMPTY_NODE; // 当前为空链表
int nStyle = MIDDLE_NODE; // 默认中间删除
CNode<T> *prior = curr->prior, *next = curr->next;
if(prior) prior->next = next;
else {start = next; nStyle = START_NODE;} // 删除的是首点
if(next) next->prior = prior;
else {last = prior; nStyle = LAST_NODE;} // 删除的是尾点
delete curr; curr = (next ? next : prior);
sum--; if(bSort) SortNo(); return nStyle; // 返回删除类型
}
// 在当前节点(0前/后1)插入,当前指向新点。默认不重排序号
template<class T>
bool CList<T>::Ins(T& dat, int bType, int bSort)
{
if(curr == NULL) return Add(dat); // 空则尾部追加
CNode<T> *info = new CNode<T>(dat); // 申请新点空间
if(!info) return false;
if(bType != 0) // 在当前点之后
{
CNode<T> *&next = curr->next; // 引用当前后继
info->prior = curr; info->next = next;
if(next) next->prior = info; else last = info;
curr = next = info; // 分尾点和中点
}
else // 在当前点之前
{
CNode<T> *&prior = curr->prior; // 引用当前前驱
info->prior = prior; info->next = curr;
if(prior) prior->next = info; else start = info;
curr = prior = info; // 分首点和中点
}
sum++; if(bSort) SortNo(); return true; // 增总数并返回
}
// 以当前首向一节点序号为基数,重新编号
template<class T>
void CList<T>::SortNo(void)
{
if(!curr) return; // 上点序号为基
curr->no = curr->prior ? curr->prior->no + 1 : 0;
CNode<T> *info = curr; // 从当前点开始
while(info->next)
{
info->next->no = info->no + 1; // 依次重新编号
info = info->next; // 不移当前指针
}
}
// (负=首向、正=尾向)移动当前指针|num|次
template<class T>
bool CList<T>::Seek(long num)
{
long count = 0, number = (num >0 ? num : -num); // 绝对移动次数
CNode<T> *info = curr;
while(info && count < number) // 是否已经足够
{
info = (num > 0 ? info->next : info->prior);// 尾向首向移动
if(info) count++;
}
if(count != number) return false; // 比较移动次数
curr = info; return true; // 当前指新位置
}
//-------------------------------------------------------------------------//
// 等号赋值函数=(置链为一新链)
template<class T>
CList<T>& CList<T>::operator = (CList<T>& list)
{
if(&list == this) return *this; // 不作自身拷贝
Destroy(); if(!list.Sum()) return *this; // 不拷贝空链表
list.Rewind(0); // 返回到首节点
do {if(!Add(list())) break;} while(list.Next());// 遍历整个链表
return *this; // 返回实例引用
}
// 等号赋值函数=(置链为单节点),无法感知dat为本身节点
template<class T>
inline CList<T>& CList<T>::operator = (T& dat)
{
Destroy(); Add(dat); return *this; // 清空追加节点
}
// 加等号赋值函数+=(尾部追加新链)
template<class T>
CList<T>& CList<T>::operator += (CList<T>& list)
{
if(&list == this || !list.Sum()) return *this; // 非自身不拷空
list.Rewind(0); // 返回到首节点
do {if(!Add(list())) break;} while(list.Next());// 遍历整个链表
return *this; // 返回实例引用
}
// 加等号赋值函数+=(尾部追加节点)
template<class T>
inline CList<T>& CList<T>::operator += (T& dat)
{
Add(dat); return *this; // 增加新单节点
}
//-------------------------------------------------------------------------//
// 链表相加操作函数
template<class T>
inline CList<T> operator + (CList<T>& list1, CList<T>& list2)
{
CList temp(list1); temp += list2; return temp; // 两个链表相加
}
// 右加节点操作函数
template<class T>
inline CList<T> operator + (CList<T>& list, T& dat)
{
CList temp(list); temp.Add(dat); return temp; // 尾部追加节点
}
// 左加节点操作函数
template<class T>
inline CList<T> operator + (T& dat, CList<T>& list)
{
CList temp(dat); temp += list; return temp; // 采用+=运算符
}
/////////////////////////////////////////////////////////////////////////////
#endif // #ifndef SCK_CLIST_CPP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -