////////////////////////////////////////////////////////////////////////////
//// Link.h
//// 适用教材:《数据结构》C++版
//// 刘大有等编著 高等教育出版社
////////////////////////////////////////////////////////////////////////////
#ifndef __LINKEDLIST_HPP__
#define __LINKEDLIST_HPP__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
extern "C" {
int exit(int);
};
//单链表结点类定义
template <class T> //结点数据域data的类型以参数 (模板)形式提供
class Node {
public: //公有成员
T data; //数据域,允许外部直接访问
private: //私有成员
Node<T> *next; //指针域(链域),指向后继结点的指针
public: //公有成员
//构造函数(初始化data和next)
Node(const T& item, Node<T> *pNext=NULL) :
data(item), next(pNext){}
//在当前结点之后插入指针p所指结点
void InsertAfter(Node<T> *p) {
if (!p) return; //若p为空,则返回
p->next = next; //将待插入结点p的next指向当前结点的next域
next = p; //将当前结点的next更新为待插入结点p
}
//删除当前结点的后继结点并返回被删除结点的地址
Node<T> *DeleteAfter() {
if (!next) return NULL; //若无后继(next为NULL),则返回
Node<T> *pNext = next; //next不为空,则记录其地址(留待函数返回后做处理)
next = next->next; //用后继结点(next)的后继来更改当前结点的next域
return pNext; //返回已记录下的待删除结点地址
}
//返回指向当前结点的后继结点的指针
Node<T> *NextNode() const { return next; }
T GetData() const { return data; }
void SetData(const T &item) { data = item; }
};
//单链表类定义
template <class T>
class LinkedList {
private:
Node<T> *front, *rear; //表头,表尾
Node<T> *currptr; //指向当前结点的指针
int size; //表长(结点的个数)
private:
//生成新结点
Node<T> *GetNode(const T& item, Node<T> *pNext = NULL) {
Node<T> *newNode;
//新分配一结点存储空间并初始化数据成员
newNode = new Node<T>(item, pNext);
if (!newNode) {
cerr << "存储空间分配失败!程序将终止。" << endl;
exit(1);
}
return newNode;
}
//释放结点p
void *freeNode(Node<T> *p) { if (p) delete p; }
private:
//当链表为空时插入结点时的处理
int InsertNewNodeWhenListIsEmpty(const T &item) {
if (size > 0) return 0; //不为空表,返回False(0)
currptr = GetNode(item);
front = currptr;
rear = currptr;
size ++;
return 1; //在空表中插入了结点,返回True(1)
}
public:
//构造函数
LinkedList() {
front = NULL;
rear = NULL;
currptr = NULL;
size = 0;
}
//拷贝构造函数
LinkedList(const LinkedList<T> &L) {
size = 0;
Node<T> *p;
p = L.front;
if (!p) { //L为空链表
front = NULL;
rear = NULL;
currptr = NULL;
return;
}
front = GetNode(p->GetData());
currptr = front;
rear = front;
p = p->NextNode();
while (p) {
rear = GetNode(p->GetData());
currptr->InsertAfter(rear);
p = p->NextNode();
currptr = rear;
}
currptr = front;
}
//析构函数
~LinkedList() {
ClearList();
}
public:
//带入运算符的重载
LinkedList<T> & operator=(const LinkedList<T> &L) {
ClearList(); //先清空当前List内容
Node<T> *p;
p = L.front; //p指向待拷贝链表L的表头
if (!p) { //L为空链表
front = NULL;
rear = NULL;
currptr = NULL;
prevptr = NULL;
return;
}
front = GetNode(p->GetData());
currptr = front;
prevptr = front;
rear = front;
p = p->NextNode();
while (p) {
rear = GetNode(p->GetData());
currptr->InsertAfter(rear);
p = p->NextNode();
currptr = rear;
}
currptr = front;
}
public:
//返回表长
int ListSize() const {
return size;
}
//判断链表是否为空
int ListEmpty() const {
return size == 0;
}
//重置当前指针currptr
void Reset(int pos = 0) {
//若pos超出范围,则返回
if (pos < 0 || pos >= size) return;
register int i = 0;
currptr = front; //从表头开始
//将currptr定位至位序为pos的结点处
while (i < pos) {
currptr = currptr->NextNode();
i ++;
}
}
//将当前指针定位至数据域取值为item的结点处
int Locate(const T &item, int bBeginFromCurrentPos = 1) {
if (size == 0) return -1; //空表时返回-1
Node<T> *p;
if (!currptr) currptr = front;
if (bBeginFromCurrentPos != 1)
p = front; //从表头结点开始
else
p = currptr; //从当前位置开始
while (p) {
if (p->GetData() == item) break; //T所对应的数据类型应支持==运算符
p = p->NextNode();
}
if (!p) return -1;
currptr = p; //定位至所找到的结点
return ThisPosition(); //返回该结点的位序
}
//移动currptr至下一结点
void Next() {
if (size == 0) return; //若为空表,则不处理
if (currptr == rear) return; //若为表尾,则不再后移
if (!currptr) { currptr = front; return; } //若为NULL则移向表头
currptr = currptr->NextNode(); //移向下一结点
}
//判断是否表尾
int EndOfList() const {
return currptr == rear;
}
//返回currptr结点位序
int ThisPosition() const {
if (size == 0) return -1; //空表时返回-1
Node<T> *p = front;
register int i = 0;
while (p && (p != currptr)) {
p = p->NextNode();
i++;
}
if (p) return i; //若找到currptr所指结点,则返回其位序
else return -1; //未找到时,返回-1
}
public:
//表头插入
void InsertFront(const T &item) {
front = GetNode(item, front);
currptr = front;
if (size == 0) rear = front;
size ++;
}
//表尾插入
void InsertRear(const T &item) {
currptr = GetNode(item);
if (size == 0)
front = currptr;
else
rear->InsertAfter(currptr);
rear = currptr;
size ++;
}
//在当前节点前插入
void InsertAt(const T &item) {
if (InsertNewNodeWhenListIsEmpty(item)) return; //链表为空时的插入
if (currptr == front) {
InsertFront(item);
return;
}
prevptr = front;
while (prevptr && (prevptr->NextNode() != currptr))
prevptr = prevptr->NextNode();
if (!prevptr) return;
currptr = GetNode(item);
prevptr->InsertAfter(currptr);
}
//在当前结点后插入
void InsertAfter(const T &item) {
if (InsertNewNodeWhenListIsEmpty(item)) return; //为空时的插入
if (!currptr) { //若currptr为空,则插入表头
currptr = GetNode(item, front);
front = currptr;
size ++;
return;
}
//在当前结点之后插入新结点
currptr->InsertAfter(GetNode(item));
if (currptr == rear) //若为表尾插入,则修改rear指针
rear = currptr->NextNode();
currptr = currptr->NextNode();
size ++;
}
//在指定位置(位序)处插入结点
void InsertAtPos(const T &item, int pos = -1) {
if (pos <= 0) { InsertFront(item); return; }
if (pos >= size) { InsertRear(item); return; }
if (size == 0) { InsertNewNodeWhenListIsEmpty(item); return; }
register int i = 1;
currptr = front;
//定位至位序为pos的结点的前驱结点处
while (currptr && (i < pos)) {
currptr = currptr->NextNode();
i ++;
}
if (!currptr) return;
currptr->InsertAfter(GetNode(item));
currptr = currptr->NextNode();
size ++;
}
//删除表头结点
void DeleteFront() {
if (!front) return; //链表已空
currptr = front->NextNode();
delete front;
front = currptr;
size --;
if (size == 0) rear = currptr; //链表已空, NULL
}
//删除当前结点
void DeleteAt() {
if (!currptr) return; //若无当前结点
if (currptr == front) { //若为表头
currptr = front->NextNode();
delete front;
front = currptr;
size --;
if (size == 0) rear = currptr; //链表已空, NULL
return;
}
Node<T> *prevptr = front;
while (prevptr) { //查找currptr的前驱结点
if (prevptr->NextNode() == currptr) break;
prevptr = prevptr->NextNode();
}
if (!prevptr) return;
if (currptr == rear) //若当前结点为表尾,则更新表尾
rear = prevptr;
prevptr->DeleteAfter(); //从链表中脱离结点currptr
delete currptr; //释放结点
if (prevptr->NextNode()) //更新currptr的值
currptr = prevptr->NextNode();
else
currptr = prevptr;
}
//删除指定位序处的结点
void DeleteAtPos(int pos = -1) {
if (pos < 1) { DeleteFront(); return; }
register int i = 1;
Node<T> *p = front;
while (p && (i < pos)) {
p = p->NextNode();
i ++;
}
if (!p) return;
currptr = p->DeleteAfter();
delete currptr;
if (p->NextNode()) //更新currptr的值
currptr = p->NextNode();
else
currptr = p;
}
//返回当前结点的数据域值(data)
T &Data() {
if (currptr)
return currptr->GetData();
//else
// return T();
}
//清空整个链表
void ClearList() {
while (front) {
currptr = front->NextNode();
delete front;
front = currptr;
}
//front = NULL;
rear = NULL;
currptr = NULL;
size = 0;
}
//输出List结点内容,每行m个。
void PrintList(
const char* sDelimiter = " ", //结点间的分隔符(串)
int m = -1, //每输出m个元素后换行,m<=0时忽略
ostream &stream = cout, //缺省输出到屏幕cout
int bEndWithNewLine = 1 //输出完毕后是否换行
) const {
Node<T> *p = front;
register int cnt = 0;
while (p) { //结点数据域类型T需支持输出运算符<<
stream << p->GetData();
if (p != rear) stream << sDelimiter;
p = p->NextNode();
if (m < 1) continue;
if (++cnt == m) {
stream << endl;
cnt = 0;
}
}
if (bEndWithNewLine && (m < 1 || cnt > 0))
stream << endl;
}
};
#endif //!__LINKEDLIST_HPP__