链表节点类和链表类代码如下,已在visual studio 2013中编译通过。
/*
以下定义了链表节点的类模板,包含两个私有成员,分别是数据域和指向下一个节点的指针(链接域)。
另外需要把链表类声明为其友元。
*/
template <class T>
class ChainNode
{
public:
template<class T> friend class Chain;//将链表类声明为其友元,使Chain可访问ChainNode所有成员(务必注意友元类模板声明格式!)
private:
T data; //链表类节点数据域
ChainNode<T>* link;//链表类节点链接域
};
/*
以下定义了链表的类模板,包含一个头指针head,指向链表第一个节点。
链表实现了以下功能:判断是否为空链表、输出长度、查找、搜索、删除、插入节点、在尾部插入节点、输出链表。
*/
template <class T>
class Chain
{
public:
Chain(){ head = NULL; tail = NULL; }
~Chain();
//删除所有节点
void DeleteAll();
//判断链表是否为空
bool IsEmpty() const { return head == NULL; }//声明为常量函数成员,使其只能读取对象内容而无权修改,保证安全性
//输出链表长度
int Length() const;
//查找链表第k个元素
bool Find(int k, T& x) const;
//搜索链表
int Search(const T& x)const;//const保证实参x不被修改
//删除一个节点
void Delete(int k, T& x);
//插入节点
void Insert(int k, const T&x);
//在尾部插入节点
void Append(const T&x);
//输出链表
void Output() const;
private:
ChainNode<T> *head;//头指针
ChainNode<T> *tail;//尾指针
};
//链表的析构函数,删除链表所有节点
//从链表的头指针开始,先把下一个节点传递给next,再delete当前节点,以此类推直到头指针为空
template <class T>
Chain<T>::~Chain()
{
ChainNode<T> *next;
while (head)
{
next = head->link;
delete head;
head = next;//移至下一个将要delete的节点
}
}
//删除所有节点,与析构函数相同
template <class T>
void Chain<T>::DeleteAll()
{
ChainNode<T> *next;
while (head)
{
next = head->link;
delete head;
head = next;//移至下一个将要delete的节点
}
}
//输出链表长度
//利用临时节点指针从头指针开始进行遍历
template <class T>
int Chain<T>::Length() const
{
int length = 0;
ChainNode<T> *curr = head;
while (curr)
{
length++;
curr = curr->link;
}
return length;//返回长度值
}
//查找链表中第k个元素
//注意查找时循环的条件index < k && curr
template <class T>
bool Chain<T>::Find(int k, T& x) const
{
if (k < 1)
return false;
ChainNode<T> *curr = head;
int index = 1;//索引curr的位置
while (index < k && curr)//使curr到达第k个元素
{
curr = curr->link;
index++;
}
if (curr)//上述循环没到第k个节点时,curr一旦为空就将停止循环,此时将输出false
{
x = curr->data;
return true;
}
return false;
}
//搜索节点
//利用临时指针节点遍历,直到为空或找到该值为止。为空找不到该值则返回0,找到则返回序号
template <class T>
int Chain<T>::Search(const T& x) const
{
ChainNode<T> *curr = head;
int index = 1;
while (curr&&curr->data != x)
{
curr = curr->link;
index++;
}
if (curr)
return index;
return 0;
}
//输出整个链表
template <class T>
void Chain<T>::Output() const
{
ChainNode<T> *curr = head;
while (curr)
{
cout << curr->data << " ";
curr = curr->link;
}
}
//删除第k个元素
//考虑三种情况:1.k<1或链表为空2.删除第一个节点3.删除其他节点
template <class T>
void Chain<T>::Delete(int k, T& x)
{
if (k < 1 || !head)
cout << "NO EXIST!";//抛出异常
else if (k == 1)
{
x = head->data;
head = head->link;
}
else
{
ChainNode<T> *q = head;
for (index = 1; index < k - 1 && q; index++)//使q指向k-1项
{
q = q->link;
}
if (!q || (!q->link))
cout << "NO EXIST!";
else
{
ChainNode<T> *p = q->link;
q->link = p->link;
if (p == tail)
tail = q;//如果删除的是最后一个节点,重定向尾指针
delete p;
}
}
}
//在第k个元素之后插入x
//如果第k个元素不存在,抛出异常;另外考虑插入为头指针的情况
template <class T>
void Chain<T>::Insert(int k, const T& x)
{
if (k < 0)
cout << "NO EXIST!";
ChainNode<T> *curr = head;
for (int index = 1; index < k&&curr; index++)//使curr指向第k个节点
curr = curr->link;
if (k>0 && !curr)
cout << "NO EXIST!";
ChainNode<T> *ins = new ChainNode < T >;
if (k)
{
ins->link = curr->link;
curr->link = ins;
if (ins->link == NULL)
tail = ins;
}
else//k=0直接插入为头节点
{
ins->link = head;
head = ins;
if (ins->link == NULL)
tail = ins;
}
}
template <class T>
void Chain<T>::Append(const T&x)
{
ChainNode<T> *curr = new ChainNode < T >;
curr->data = x;
curr->link = NULL;
if (head)//链表非空
{
tail->link = curr;
tail = curr;
}
else//链表为空
head = tail = curr;
}