单向链表的节点类模板和链表类模板

来源:互联网 发布:myeclipse里用数据库 编辑:程序博客网 时间:2024/04/29 16:42

1.定义结点类模板:CNode.h


插入操作算法


删除操作算法


#ifndef CNODE_INCLUDE_H#define CNODE_INCLUDE_H//结点类模板的定义template <class T> class CNode{private:CNode<T> *next;  //指向后继结点的指针(指针域)public:T data;  //数据域CNode(const T& data, CNode<T> *next = 0);  //构造函数void InsertAfter(CNode<T> *p);  //在本节点之后插入一个同类结点pCNode<T>* DeleteAfter();  //删除本节点的后继结点,并返回其地址CNode<T>* NextNode();  //获取后继结点的地址const CNode<T> *NextNode()const;  //获取后继结点的地址(常函数)};/*构造函数*/template <class T> CNode<T>::CNode(const T& data, CNode<T> *next = 0) :data(data), next(next){}/*返回后继结点的指针*/template <class T> CNode<T>* CNode<T>::NextNode(){return next;}/*在当前结点之后插入一个结点p*/template <class T> void CNode<T>::InsertAfter(CNode<T> *p){p->next = next;  //p结点指针域指向当前节点的后继结点next = p;  //当前节点的指针域指向p}/*删除当前结点的后继结点,并返回其地址*/template <class T> CNode<T>* CNode<T>::DeleteAfter(){CNode<T> *tempPtr = next;  //将欲删除的节点地址存储到tempPtrif (next == 0)  //如果当前节点没有后继结点,则返回空指针return 0;next = tempPtr->next;  //使当前节点的指针域指向tempPtr的后继结点return tempPtr;}#endif

2.链表类模板的定义:

#ifndef LINKEDLIST_INCLUDE_H#define LINKEDLIST_INCLUDE_H#include "CNode.h"//链表类模板template <class T> class LinkedList{private://私有数据成员CNode<T> *front, *rear;  //表头和表尾指针CNode<T> *prevPtr, *currPtr;  //记录当前遍历位置的指针,由插入和删除操作更新int size;  //表中的元素个数int position;  //当前元素在表中的位置序号,由函数reset使用//私有函数成员,用于本类的内部函数调用CNode<T>* NewNode(const T& item, CNode<T>* ptrNext = NULL);  //生成新节点,数据域为item,指针域为ptrNextvoid FreeNode(CNode<T>* p);  //释放节点void Copy(const LinkedList<T>& L);  //将链表L拷贝到当前表(假设当前表为空),被拷贝构造函数,operator=调用public://共有成员函数LinkedList();  //构造函数LinkedList(const LinkedList<T> &L);  //拷贝构造函数~LinkedList();  //析构函数LinkedList<T>& operator=(const LinkedList<T>& L);  //重载赋值运算符int GetSize()const;  //返回链表中的元素个数bool IsEmpty()const;  //链表是否为空void ReSet(int pos = 0);  //初始化游标的位置void Next();  //使游标移动到下一个节点bool EndOfList()const;  //游标是否到了链尾int CurrentPosition()const;  //返回游标当前的位置void InsertFront(const T& item);  //在表头插入结点void InsertRear(const T& item);  //在表尾插入结点void InsertAt(const T& item);  //在当前结点之前插入结点void InsertAfter(const T& item);  //在当前结点之后插入结点T DeleteFront();  //删除头结点void DeleteCurrent();  //删除当前结点T& data();  //返回当前节点成员数据的引用const T& data()const;  //返回当前节点的数据应用(常函数)void Clear();  //清空链表:释放所有结点的内存空间。被析构函数调用};/*生成新节点*/template <class T> CNode<T>* LinkedList<T>::NewNode(const T& item, CNode<T>* ptrNext){CNode<T>* p;p = new CNode<T>(item, ptrNext);if (p == NULL){cout << "Memory allocation failure!" << endl;exit(1);}return p;}/*释放节点*/template <class T> void LinkedList<T>::FreeNode(CNode<T>* p){delete p;}/*复制链表*/template <class T> void LinkedList<T>::Copy(const LinkedList<T>& L){CNode<T> *p = L.front;  //p用来遍历Lint pos;while (p != NULL)  //将L中的每一个元素插入到当前连接表最后{InsertRear(p->data);p = p->NextNode();}if (position == -1) //如果链表为空,则返回return;//在新链表中重新设置prevPtr和currptrprevPtr = NULL;currPtr = front;for (pos = 0; pos != position; pos++){prevPtr = currPtr;currPtr = currPtr->NextNode();}}/*构造函数,构造新链表,size为0,positon为-1*/template <class T> LinkedList<T>::LinkedList() :front(NULL), rear(NULL), prevPtr(NULL), currPtr(NULL), size(0), position(-1){}/*拷贝构造函数*/template <class T>LinkedList<T>::LinkedList(const LinkedList<T>& L){front = rear = NULL;prevPtr = currPtr = NULL;size = 0;position = -1;Copy(L);}/*析构函数*/template <class T> LinkedList<T>::~LinkedList(){Clear();}/*重载赋值运算符*/template <class T> LinkedList<T>& LinkedList<T>::operator=(const LinkedList<T>& L){if (this == &L)  //不能将链表赋值给它自身return *this;Clear();Copy(L);return *this;}/*获取链表的大小*/template <class T> int LinkedList<T>::GetSize()const{return size;}/*判断链表是否为空*/template <class T> bool LinkedList<T>::IsEmpty()const{return size == 0;}/*将链表当前位置设置为pos*/template <class T>void LinkedList<T>::ReSet(int pos){int startPos;if (front == NULL) //如果链表为空return;if (pos<0 || pos>size - 1)  //如果指定位置不合法,返回{cerr << "ReSet:Invalid list position: " << pos << endl;return;}//设置与链表有关的成员if (pos == 0)  //如果pos为0,将指针重新设置到表头{prevPtr = NULL;currPtr = front;position = 0;}else  //否则重新设置currPtr,prevPtr,position{currPtr = front->NextNode();prevPtr = front;startPos = 1;for (position = startPos; position!=pos; position++){prevPtr = currPtr;currPtr = currPtr->NextNode();}}}/*将prevPtr和currPtr先前移动一个结点*/template <class T>void LinkedList<T>::Next(){if (currPtr != NULL){prevPtr = currPtr;currPtr = currPtr->NextNode();position++;}}/*判断是否已到达链表尾*/template <class T> bool LinkedList<T>::EndOfList()const{return currPtr == NULL;}/*返回当前节点的位置*/template <class T> int LinkedList<T>::CurrentPosition()const{return position;}/*将item插入在表头*/template <class T> void LinkedList<T>::InsertFront(const T& item){if (front != NULL)  //如果链表不为空,则调用ReSet()ReSet();InsertAt(item);  //在表头插入}/*在表尾插入结点*/template <class T> void LinkedList<T>::InsertRear(const T& item){CNode<T> *nNode;prevPtr = rear;nNode = NewNode(item);  //创建新节点if (rear == NULL)  //如果表为空,则插入在表头front = rear = nNode;else{rear->InsertAfter(nNode);rear = nNode;}currPtr = rear;position = size;size++;}/*将item插入在当前位置*/template <class T> void LinkedList<T>::InsertAt(const T& item){CNode<T> *nNode;if (prevPtr == NULL)  //插入在链表头,包括将结点插入到空表中{nNode = NewNode(item, front);front = nNode;}else  //插入到链表之中,将结点置于prevPtr之后{nNode = NewNode(item);prevPtr->InsertAfter(nNode);}if (prevPtr == rear)//正在向空表中插入,或者是插入到非空表的表尾{rear = nNode;  //更新rearposition = size;   //更新position}currPtr = nNode;  //更新currPtrsize++;  //更新szie}/*将item插入到当前位置之后*/template <class T>void LinkedList<T>::InsertAfter(const T& item){CNode<T> *p;p = NewNode(item);if (front == NULL)  //向空链表中插入{front = currPtr = rear = p;position = 0;}else  //插入到{if (currPtr == NULL)currPtr = prevPtr;currPtr->InsertAfter(p);if (currPtr == rear){rear = p;position = szie;}elseposition++;prevPtr = currPtr;currPtr = p;}size++;  //更新链表长度}/*删除表头结点*/template <class T> T LinkedList<T>::DeleteFront(){T item;ReSet();if (front == NULL){cerr << "Invalid deletion!" << endl;exit(1);}item = currPtr->data;DeleteCurrent();return item;}/*删除链表当前位置的结点*/template <class T> void LinkedList<T>::DeleteCurrent(){CNode<T> *p;if (currPtr == NULL)//如果链表为空或者到达表尾{cerr << "Invalid deletion!" << endl;exit(1);}if (prevPtr == NULL) //删除操作发生在表头或者表中{p = front;  //保存头结点地址front = front->NextNode();  //将其从链表分离}else  //分离prevPtr之后的一个内部结点,保存其地址{p = prevPtr->DeleteAfter();}if (p == rear)  //如果尾节点被删除{rear = prevPtr;  //新的表尾是prevPtrposition--;  //position回退一步}currPtr = p->NextNode();  //使currPtr越过被删除的结点FreeNode(p);  //释放节点,并使链表长度减-size--;}//返回一个当前节点的数值引用template <class T>T& LinkedList<T>::data(){if (size == 0 || currPtr == NULL) //如果链表为空,或者到达链表尾{cerr << "Data:invalid reference!" << endl;exit(1);}return currPtr->data;}/*清空链表*/template <class T> void LinkedList<T>::Clear(){CNode<T> *currPosition, *nextPosition;currPosition = front;while (currPosition != NULL){nextPosition = currPosition->NextNode(); //取得下一个结点的地址FreeNode(currPosition);//删除当前节点currPosition = nextPosition;  //当前指针移到下一个结点}front = rear = NULL;prevPtr = currPtr = NULL;size = 0;position = -1;}#endif

3.测试代码:

#include <iostream>#include "LinkedList.h"using namespace std;int main() {LinkedList<int> list;for (int i = 0; i < 10; i++){int item;cin >> item;list.InsertFront(item);  //在表头插入}cout << "list:";list.ReSet();while (!list.EndOfList()){cout << list.data() << " ";list.Next(); //指针下移}cout << endl;int key;  //词条,用于删除cout << "Please enter some integer needed to be deleted:";cin >> key;list.ReSet();while (!list.EndOfList()){if (list.data() == key)list.DeleteCurrent();list.Next(); //指针下移}cout << "list:";list.ReSet();while (!list.EndOfList()){cout << list.data() << " ";list.Next();}cout << endl;return 0;}

测试结果:



来自清华大学MOOC课件


0 0
原创粉丝点击