数据结构和算法C++语言实现:链表的实现

1、设计一个类来实现ADT牵涉到标识出那些需要来实现ADT操作的函数成员,如果最终能够获得一个计划良好易于使用的类,那么在这个阶段所花费的时间最终将得到回报。我们还需要认识到,我们对函数成员的描述与这个类将如何实现是没有关系的。

2、设计一个链表,为了保证封装性,需要将类型定义在类的内部:

class List
{
private:
	class Node
	{
	public:
		Node *pNext;
		T m_data;

		Node()
		{
			m_data = 0;
			pNext = NULL;
		}
	};
	//typedef Node * Link_List;
	int m_Lenth;
	//Link_List pHead;
	Node *pHead;
}

链表的数据类型定义在类的内部,应用类的嵌套的方式

3、考虑到类的定义的完整性,需要给类添加如下的功能

 构造、析构、拷贝构造函数、操作符的重载

public:
	List();
	List(const List &m_List);
	~List();
	const List&operator=(const List &m_List);

       在作为ADT的链表的定义中,还需要如下的操作:判空,插入、删除、遍历、输出显示、修改、查询

<span style="white-space:pre">	</span>bool List_IsEmpty();
	int  List_Lenth();
	void List_Insert(T num,int nPos);
	void List_Delete(int nPos);
	void List_Destroy();
	void List_Display();
	Node * List_GetHead() const;
	bool List_FindElem(T num);
	void List_Modify(T num, int nPos);


4、接口的具体实现如下:

template<typename T>
List<T>::List(const List<T> &m_List)
{
	Node *pTempNode = m_List.pHead;
	this->pHead = new Node;
	this->m_Lenth =0;
	assert(pHead);

	Node *pNewHead = pHead;
	if(NULL ==pTempNode)
	{
		cout<<"List doesn't exists"<<endl;
		return;
	}
	
	pTempNode = pTempNode->pNext;
	while(NULL!=pTempNode)
	{
		Node *pTemp = new Node;
		if(NULL!=pTemp)
		{
			pTemp->m_data = pTempNode->m_data;
			pTemp->pNext = NULL;
		}

		pNewHead->pNext = pTemp;
		pNewHead = pNewHead->pNext;
		pTempNode = pTempNode->pNext;
		++m_Lenth;
	}
	//m_Lenth = m_List.m_Lenth;
}

<pre name="code" class="csharp">template<typename T>
const List<T>&List<T>::operator=(const List<T> &m_List)
{
	if (this == &m_List)
		return *this;

	Node *pTempHead = this->pHead->pNext;
	Node *pTempNode = m_List.pHead->pNext;
	if(NULL ==pTempNode)
	{
		cout<<"List doesn't exists"<<endl;
		exit(0);
	}


	while(NULL!=pTempHead)
	{
		Node *pTemp = pTempHead;
		pTempHead = pTempHead->pNext;
		delete pTemp;
	}

	pTempHead = this->pHead;
	while(NULL!=pTempNode)
	{
		Node *pTemp = new Node;
		if(NULL!=pTemp)
		{
			pTemp->m_data = pTempNode->m_data;
			pTemp->pNext = NULL;
		}

		pTempHead->pNext = pTemp;
		pTempHead = pTempHead->pNext;
		pTempNode = pTempNode->pNext;
		++m_Lenth;
	}
	//m_Lenth = m_List.m_Lenth;

	return *this;
}


 上面的两个接口是拷贝构造函数和“=”操作符的重载,两个函数内部实现的方式类似,但是功能却差别很大,具体的差别见前面的文章中的叙述,这里需要注意的有如下几点: 

     1)、幅值操作符“= ” 返回一个 *this

     2)、赋值操作符中应进行证同测试

     3)、赋值时,对象中的每一部分都要进行复制

template<typename T>
void List<T>::List_Insert(T num,int nPos)
{
	Node *pTempHead = this->pHead;
	if(NULL == pTempHead)
	{
		cout<<"List is NULL ,can't Insert"<<endl;
		return ;
	}

	if(nPos<=0||nPos>m_Lenth+1)
	{
		cout<<"Invalide Position"<<endl;
		return;
	}

	int m_Count = 0;
	Node *pNewNode = new Node;
	pNewNode->m_data = num;
	pNewNode->pNext = NULL;
	while(NULL!=pTempHead)
	{
		
		++m_Count;
		if(m_Count==nPos)
		{
			pNewNode->pNext = pTempHead->pNext;
			pTempHead->pNext = pNewNode;

			break;
		}

		pTempHead = pTempHead->pNext;
	}

	++m_Lenth;
}

template<typename T>
void List<T>::List_Delete(int nPos)
{
	Node *pTempHead = this->pHead;
	if(NULL == pTempHead||nPos>m_Lenth+1)
	{
		cout<<"can't Delete"<<endl;
		return ;
	}

	int m_Count = 0;
	while(NULL!=pTempHead)
	{
		++m_Count;
		if(m_Count == nPos)
		{
			Node *pTemp = pTempHead->pNext;
			pTempHead->pNext = pTemp->pNext;
			delete pTemp;

			break;
		}

		pTempHead = pTempHead->pNext;
	}

	--m_Lenth;
}

插入和删除中需要注意遍历的过程中不要越界,进行判空检查,否则会出现意想不到的错误。

template<typename T>
<span style="color:#ff6666;">typename List<T>::Node * List<T>::List_GetHead() const</span>
{
	return pHead;
}

注意上面红色的部分,类模板之间嵌套时需要按照上面的方式进行调用,否则系统会报错。


void main()
{
	List<int> myList;
	for(int i=0;i<12;i++)
	{
		myList.List_Insert(i,1);
	}

	myList.List_Insert(15,7);
	cout<<"**myList:"<<myList.List_Lenth()<<endl;
	myList.List_Display();

	List<int> newList = myList;
	cout<<"**newList:"<<newList.List_Lenth()<<endl;
	newList.List_Display();

	myList.List_Insert(101,9);
	List<int> newOpList;
	newOpList = myList;
	cout<<"**newOpList:"<<newOpList.List_Lenth()<<endl;
	newOpList.List_Display();


	for(int i=0;i<5;i++)
		newOpList.List_Delete(1);
	cout<<"**newOpList:"<<newOpList.List_Lenth()<<endl;
	newOpList.List_Display();
	
	newOpList.List_Destroy();

	system("pause");
}
调试程序,输出如下的结果:






  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NUDT程序设计模拟测试 1. 请创建一个数据类型为T的链表类模板List,实现以下成员函数: 1) 默认构造函数List(),将该链表初始化为一个空链表(10分) 2) 拷贝构造函数List(const List& list),根据一个给定的链表构造当前链表(10分) 3) 析构函数~List(),释放链表中的所有节点(10分) 4) Push_back(T e)函数,往链表最末尾插入一个元素为e的节点(10分) 5) operator<<()友元函数,将链表的所有元素按顺序输出(10分) 6) operator=()函数,实现两个链表的赋值操作(10分) 7) operator+()函数,实现两个链表的连接,A=B+C(10分) 2. 请编写main函数,测试该类模板的正确性: 1) 用List模板定义一个List类型的模板类对象int_listB,从键盘读入m个整数,调用Push_back函数将这m个整数依次插入到该链表中;(4分) 2) 用List模板定义一个List类型的模板类对象int_listC,从键盘读入n个整数,调用Push_back函数将这n个整数依次插入到该链表中;(4分) 3) 用List模板定义一个List类型的模板类对象int_listA,调用List的成员函数实现A = B + C;(4分) 4) 用cout直接输出int_listA的所有元素(3分) 5) 用List模板定义List类型的模板类对象double_listA, double_listB, double_listC,重复上述操作。(15分) 3. 输入输出样例: 1) 输入样例 4 12 23 34 45 3 56 67 78 3 1.2 2.3 3.4 4 4.5 5.6 6.7 7.8 2) 输出样例 12 23 34 45 56 67 78 1.2 2.3 3.4 4.5 5.6 6.7 7.8

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值