2017/2/1 修改
///
// LinkList.h : CLinkList 单链表类
//
#include <assert.h>
// 节点类
template <class Type>
class CNode {
// 方法
public :
CNode()
{
m_pNext = 0;
}
// 属性
public :
Type m_data;
CNode * m_pNext;
};
// 单链表类
template <class Type>
class CLinkList {
// 方法
public :
// 构造
CLinkList();
CLinkList(Type arrInitial[], int iLen);
// 析构
~CLinkList();
// 销毁
void Destroy();
// 是否为空
bool IsEmpty();
// 取链表长度
int GetSize();
// 以序号查找节点(-1表示根节点, 超出链表范围返回尾结点)
CNode<Type> * GetNodeFromID(int iIndex);
CNode<Type> * operator [] (int iIndex);
// 以内容查找节点
CNode<Type> * GetNodeFromData(Type data);
// 以内容查找序号(失败返回-1)
int Find(Type data);
// 插入
bool AddAt(int iIndex, Type data);
// 在末尾处加入
bool AddBack(Type data);
// 删除
bool Delete(int iIndex);
bool Delete(int iIndex, Type * data);
// 属性
private :
// 头结点,尾结点
CNode<Type> * m_pHead, * m_pTail;
// 链表长度
int m_iSize;
};
// 构造
template <class Type>
CLinkList<Type>::CLinkList()
{
m_pHead = new CNode<Type>();
m_pTail = m_pHead;
m_iSize = 0;
}
// 构造
template <class Type>
CLinkList<Type>::CLinkList(Type arrInitial[], int iLen)
{
m_pHead = new CNode<Type>();
m_pTail = m_pHead;
m_pHead->m_pNext = 0;
m_iSize = 0;
for (int i = 1; i <= iLen; i++)
AddBack(arrInitial[i - 1]);
}
// 析构
template <class Type>
CLinkList<Type>::~CLinkList()
{
Destroy();
delete m_pHead;
}
// 销毁
template <class Type>
void CLinkList<Type>::Destroy()
{
CNode<Type> * p, * q;
p = m_pHead;
while(p)
{
q = p;
p = p->m_pNext;
delete q;
}
m_iSize = 0;
}
// 是否为空
template <class Type>
bool CLinkList<Type>::IsEmpty()
{
return (!m_iSize);
//return (m_pHead->m_pNext == 0);
}
// 以序号查找节点
template <class Type>
CNode<Type> * CLinkList<Type>::GetNodeFromID(int iIndex)
{
// 我们经常会需要在链表尾部添加节点,
// 如果频繁地使用 GetNodeFromID() 获取尾部节点,可能耗时较长,
// 因此这样写
if (iIndex >= GetSize() - 1)
return m_pTail;
if (iIndex == -1)
return m_pHead;
assert(!IsEmpty());
if (IsEmpty())
return 0;
assert(iIndex >= 0);
assert(iIndex < GetSize());
if (iIndex < 0 || iIndex >= GetSize())
return 0;
CNode<Type> * pTmp = m_pHead->m_pNext;
while(pTmp && iIndex)
{
pTmp = pTmp->m_pNext;
iIndex--;
}
return pTmp;
}
// 以内容查找节点
template <class Type>
CNode<Type> * CLinkList<Type>::GetNodeFromData(Type data)
{
assert(!IsEmpty());
if (IsEmpty())
return 0;
CNode<Type> * pTmp = m_pHead->m_pNext;
while (pTmp)
{
if (pTmp->m_data != data)
pTmp = pTmp->m_pNext;
else
return pTmp;
}
return 0;
}
// 以内容查找序号
template <class Type>
int CLinkList<Type>::Find(Type data)
{
assert(!IsEmpty());
if (IsEmpty())
return 0;
CNode<Type> * pTmp = m_pHead->m_pNext;
int i = 0;
while (pTmp)
{
if (pTmp->m_data != data)
{
pTmp = pTmp->m_pNext;
i++;
}
else
return i;
}
return -1;
}
// 取链表长度
template <class Type>
int CLinkList<Type>::GetSize()
{
/*
int iSize = 0;
CNode<Type> * pTmp = m_pHead->m_pNext;
while (pTmp)
{
iSize++;
pTmp = pTmp->m_pNext;
}
return iSize;
*/
// 上面这种办法是可行的,但是有一个更简单的方法
return m_iSize;
}
// 以序号查找节点(运算符重载)
template <class Type>
CNode<Type> * CLinkList<Type>::operator [] (int iIndex)
{
return GetNodeFromID(iIndex);
}
// 插入
template <class Type>
bool CLinkList<Type>::AddAt(int iIndex, Type data)
{
CNode<Type> * p, * pLast;
pLast = GetNodeFromID(iIndex - 1);
assert(pLast);
if (!pLast)
return false;
p = new CNode<Type>();
p->m_data = data;
p->m_pNext = pLast->m_pNext;
pLast->m_pNext = p;
if (iIndex == GetSize())
m_pTail = p;
m_iSize++;
return true;
}
// 在末尾处加入
template <class Type>
bool CLinkList<Type>::AddBack(Type data)
{
return AddAt(GetSize(), data);
}
// 删除
template <class Type>
bool CLinkList<Type>::Delete(int iIndex)
{
CNode<Type> * pLast, * p;
pLast = GetNodeFromID(iIndex - 1);
assert(pLast);
if (!pLast)
return false;
p = pLast->m_pNext;
assert(p);
if (!p)
return false;
pLast->m_pNext = p->m_pNext;
delete p;
if (iIndex == GetSize())
m_pTail = pLast;
m_iSize--;
return true;
}
// 删除
template <class Type>
bool CLinkList<Type>::Delete(int iIndex, Type * data)
{
*data = GetNodeFromID(iIndex) -> m_data;
return Delete(iIndex);
}
///
// test1.cpp : 测试程序
// 从A中去除B中已存在的元素,保存到C中
//
#include <iostream>
#include <cstdio>
#include "LinkList.h"
using namespace std;
int main()
{
int arrA[] = {1, 2, 3, 4, 5, 6, 7};
int arrB[] = {5, 7, 8, 9};
CLinkList<int> linkA(arrA, sizeof(arrA) / sizeof(int));
CLinkList<int> linkB(arrB, sizeof(arrB) / sizeof(int));
linkA.Delete(4);
linkB.AddAt(3, 2);
printf("单链表 A 中的元素个数:%d\n", linkA.GetSize());
printf(" ");
for (int i = 1; i <= linkA.GetSize(); i++)
cout << linkA[i - 1]->m_data << " ";
cout << endl;
printf("单链表 B 中的元素个数:%d\n", linkB.GetSize());
printf(" ");
for (int i = 1; i <= linkB.GetSize(); i++)
cout << linkB[i - 1]->m_data << " ";
cout << endl;
CLinkList<int> linkC;
for (int i = 1; i <= linkA.GetSize(); i++)
{
if (linkB.Find(linkA[i - 1]->m_data) == -1)
linkC.AddBack(linkA[i - 1]->m_data);
}
printf("单链表 A - B 中的元素个数:%d\n", linkC.GetSize());
printf(" ");
for (int i = 1; i <= linkC.GetSize(); i++)
cout << linkC[i - 1]->m_data << " ";
cout << endl;
return 0;
}
///
// test2.cpp : 测试程序
// 合并链表
//
#include <iostream>
#include <cstdio>
#include "LinkList.h"
using namespace std;
template <class Type>
void PrintList(const char str[], CLinkList<Type> * list)
{
printf("链表 %s 共有 %d 个元素:\n", str, list->GetSize());
cout << " ";
for (int i = 1; i <= list->GetSize(); i++)
cout << list->GetNodeFromID(i - 1)->m_data << " ";
cout << endl;
}
int main()
{
int arr[] = {1, 8, 3, 4, 5};
CLinkList<int> list1(arr, 5);
PrintList("list1", &list1);
int iData;
list1.Delete(1, &iData);
cout << endl << "删除链表中的第二个节点:" << iData << endl;
PrintList("list1", &list1);
cout << endl << "在第一个元素值等于4的节点前插入一个元素值为7的节点。" << endl;
list1.AddAt(list1.Find(4), 7);
PrintList("list1", &list1);
cout << endl;
int arr2[] = {9, 8, 6, 5};
CLinkList<int> list2(arr2, 4);
PrintList("list2", &list2);
cout << endl << "把两条链表合并" << endl;
for (int i = 1; i <= list2.GetSize(); i++)
list1.AddBack(list2[i - 1]->m_data);
PrintList("list1 + list2", &list1);
}
-----------------------------------------------------------------------------------
下面是初始版本的代码:
不知道有没有错误。
///
// LinkList.h : CLinkList 单链表类
//
#include <assert.h>
// 节点类
template <class Type>
class CNode {
// 方法
public :
CNode()
{
m_pNext = 0;
}
// 属性
public :
Type m_data;
CNode * m_pNext;
};
// 单链表类
template <class Type>
class CLinkList {
// 方法
public :
// 构造
CLinkList();
CLinkList(Type arrInitial[], int iLen);
// 析构
~CLinkList();
// 销毁
void Destroy();
// 是否为空
bool IsEmpty();
// 取链表长度
int GetSize();
// 以序号查找节点(-1表示根节点)
CNode<Type> * GetNodeFromID(int iIndex);
CNode<Type> * operator [] (int iIndex);
// 以内容查找节点
CNode<Type> * GetNodeFromData(Type data);
// 以内容查找序号(失败返回-1)
int Find(Type data);
// 插入
bool Insert(int iIndex, Type data);
// 在末尾处加入
bool Add(Type data);
// 删除
bool Delete(int iIndex);
bool Delete(int iIndex, Type * data);
// 属性
private :
// 头结点
CNode<Type> * m_pHead;
};
// 构造
template <class Type>
CLinkList<Type>::CLinkList()
{
m_pHead = new CNode<Type>();
m_pHead->m_pNext = 0;
}
// 构造
template <class Type>
CLinkList<Type>::CLinkList(Type arrInitial[], int iLen)
{
m_pHead = new CNode<Type>();
m_pHead->m_pNext = 0;
for (int i = 1; i <= iLen; i++)
Add(arrInitial[i - 1]);
}
// 析构
template <class Type>
CLinkList<Type>::~CLinkList()
{
Destroy();
delete m_pHead;
}
// 销毁
template <class Type>
void CLinkList<Type>::Destroy()
{
CNode<Type> * p, * q;
p = m_pHead;
while(p)
{
q = p;
p = p->m_pNext;
delete q;
}
}
// 是否为空
template <class Type>
bool CLinkList<Type>::IsEmpty()
{
return (m_pHead->m_pNext == 0);
}
// 以序号查找节点
template <class Type>
CNode<Type> * CLinkList<Type>::GetNodeFromID(int iIndex)
{
if (iIndex == -1)
return m_pHead;
assert(!IsEmpty());
if (IsEmpty())
return 0;
assert(iIndex >= 0);
assert(iIndex < GetSize());
if (iIndex < 0 || iIndex >= GetSize())
return 0;
CNode<Type> * pTmp = m_pHead->m_pNext;
while(pTmp && iIndex)
{
pTmp = pTmp->m_pNext;
iIndex--;
}
return pTmp;
}
// 以内容查找节点
template <class Type>
CNode<Type> * CLinkList<Type>::GetNodeFromData(Type data)
{
assert(!IsEmpty());
if (IsEmpty())
return 0;
CNode<Type> * pTmp = m_pHead->m_pNext;
while (pTmp)
{
if (pTmp->m_data != data)
pTmp = pTmp->m_pNext;
else
return pTmp;
}
return 0;
}
// 以内容查找序号
template <class Type>
int CLinkList<Type>::Find(Type data)
{
assert(!IsEmpty());
if (IsEmpty())
return 0;
CNode<Type> * pTmp = m_pHead->m_pNext;
int i = 0;
while (pTmp)
{
if (pTmp->m_data != data)
{
pTmp = pTmp->m_pNext;
i++;
}
else
return i;
}
return -1;
}
// 取链表长度
template <class Type>
int CLinkList<Type>::GetSize()
{
int iSize = 0;
CNode<Type> * pTmp = m_pHead->m_pNext;
while (pTmp)
{
iSize++;
pTmp = pTmp->m_pNext;
}
return iSize;
}
// 以序号查找节点(运算符重载)
template <class Type>
CNode<Type> * CLinkList<Type>::operator [] (int iIndex)
{
return GetNodeFromID(iIndex);
}
// 插入
template <class Type>
bool CLinkList<Type>::Insert(int iIndex, Type data)
{
CNode<Type> * p, * pLast;
pLast = GetNodeFromID(iIndex - 1);
assert(pLast);
if (!pLast)
return false;
p = new CNode<Type>();
p->m_data = data;
p->m_pNext = pLast->m_pNext;
pLast->m_pNext = p;
return true;
}
// 在末尾处加入
template <class Type>
bool CLinkList<Type>::Add(Type data)
{
return Insert(GetSize(), data);
}
// 删除
template <class Type>
bool CLinkList<Type>::Delete(int iIndex)
{
CNode<Type> * pLast, * p;
pLast = GetNodeFromID(iIndex - 1);
assert(pLast);
if (!pLast)
return false;
p = pLast->m_pNext;
assert(p);
if (!p)
return false;
pLast->m_pNext = p->m_pNext;
delete p;
return true;
}
// 删除
template <class Type>
bool CLinkList<Type>::Delete(int iIndex, Type * data)
{
*data = GetNodeFromID(iIndex) -> m_data;
return Delete(iIndex);
}
(顺便说一句,那个 GetNodeFromID() 和 GetNodeFromData() 不能写成重载函数,因为后者的参数 data 的类型有可能是 int )
测试代码(从A中去除B中已存在的元素,保存到C中):
#include <iostream>
#include <cstdio>
#include "LinkList.h"
using namespace std;
int main()
{
int arrA[] = {1, 2, 3, 4, 5, 6, 7};
int arrB[] = {5, 7, 8, 9};
CLinkList<int> linkA(arrA, sizeof(arrA) / sizeof(int));
CLinkList<int> linkB(arrB, sizeof(arrB) / sizeof(int));
linkA.Delete(4);
printf("单链表 A 中的元素个数:%d\n", linkA.GetSize());
printf(" ");
for (int i = 1; i <= linkA.GetSize(); i++)
cout << linkA[i - 1]->m_data << " ";
cout << endl;
printf("单链表 B 中的元素个数:%d\n", linkB.GetSize());
printf(" ");
for (int i = 1; i <= linkB.GetSize(); i++)
cout << linkB[i - 1]->m_data << " ";
cout << endl;
CLinkList<int> linkC;
for (int i = 1; i <= linkA.GetSize(); i++)
{
if (linkB.Find(linkA[i - 1]->m_data) == -1)
linkC.Add(linkA[i - 1]->m_data);
}
printf("单链表 A - B 中的元素个数:%d\n", linkC.GetSize());
printf(" ");
for (int i = 1; i <= linkC.GetSize(); i++)
cout << linkC[i - 1]->m_data << " ";
cout << endl;
return 0;
}