[C++]数据结构之单链表

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值