编程语言

img YangJq

单链表结构的实现(C++版, Link.h)

发表于2004/10/12 22:27:00  1769人阅读

分类: 数据结构2004

////////////////////////////////////////////////////////////////////////////
//// 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;
        size ++;
        rear = front;
        p = p->NextNode();
        while (p) {
            rear = GetNode(p->GetData());
            currptr->InsertAfter(rear);
            size ++;
            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 *this;
        }
        front = GetNode(p->GetData());
        currptr = front;
        prevptr = front;
        rear = front;
        size ++;
        p = p->NextNode();
        while (p) {
            rear = GetNode(p->GetData());
            currptr->InsertAfter(rear);
            size ++;
            p = p->NextNode();
            currptr = rear;
        }
        currptr = front;
        return *this;
    }
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__

阅读全文
0 0

相关文章推荐

img
取 消
img