[C++] 利用模板的模板参数实现单链表

模板的模板顾名思义就是一个模板函数的参数是另一个模板函数的模板。

模板函数有兴趣的读者请看我上一篇博客模板函数,实现顺序表

请看模板的模板简要举例

wKiom1bqzPqjAUeNAABa09vu3wo286.png

wKiom1bqzRfi_tfDAABaLtP412Y231.png

上边两张图片就是模板的模板类型了,模板的模板也可以使用缺省参数(这一点与函数相似)

wKioL1bqzlaCsQO4AAAb7ewusdU016.png

好了上面介绍过了,现在直接上代码吧,我个人觉得一个函数怎么用,还是直接看实例更容易让人懂,

下面是单链表的节点类, 用的是模板函数

#pragma once
#include<iostream>
using namespace std;

#include<string>

template<typename DataType>
struct SListNode   //单链表的节点
{
	SListNode(DataType x)
		:_data(x),
		_next(NULL)
	{}

	SListNode *_next;
	DataType _data;
};

下面列出单链表类以及主要的函数,也是模板的模板,

template<class DataType, class SListNode = SListNode<DataType> >
class SList
{
public:
	SList();
	SList(const SList&s);
	SList& operator=(SList s);
	~SList();
	void PushBack(DataType x);  //尾插
	void PopBack();  //尾删
	void PushFront(DataType x);
	void PopFront();
	void Insert(const SListNode* pos, DataType x);
	void PrintSList();
	void Clear();

private:
	SListNode*_head;
	SListNode *_tail;
};

下边列出构造函数、赋值运算符重载函数、以及析构函数

template<class DataType, class SListNode = SListNode<DataType> >
SList<DataType, SListNode>::SList()
:_head(NULL),
_tail(NULL)
{}

template<class DataType, class SListNode = SListNode<DataType> >
SList<DataType, SListNode>::SList(const SList&s)
: _head(NULL),
_tail(NULL)
{
	SListNode *cur = s._head;
	while (cur)
	{
		this->PushBack(cur->_data);
		cur = cur->_next;
	}
}

template<class DataType, class SListNode = SListNode<DataType> >
SList<DataType, SListNode>& SList<DataType, SListNode>::operator=(SList s)
{
	swap(_head, s._head);
	swap(_tail, s._tail);
	return *this;
}

//template<class DataType, class SListNode = SListNode<DataType> >
//SList<DataType, SListNode>& SList<DataType, SListNode>::operator=(SList s)
//{
//	if (this != &s)
//	{
//		this->Clear();
//		SListNode *cur = s._head;
//		while (cur)
//		{
//			this->PushBack(cur->_data);
//			cur = cur->_next;
//		}
//	}
//	return *this;
//}


template<class DataType, class SListNode = SListNode<DataType> >
SList<DataType, SListNode>:: ~SList()
{
	Clear();
}

template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::Clear()
{
	SListNode* cur = _head;
	while (cur)
	{
		SListNode *del = cur;
		cur = cur->_next;
		delete del;
	}
	_head = NULL;
}

下边列出插入删除函数

template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PushBack(DataType x)
{
	if (_head == NULL)
	{
		_head = new SListNode(x);
		_tail = _head;
		//SList temp(x);//现代写法
		//swap(_head, temp._head);
		//swap(_tail, temp._tail);
	}
	else
	{
		_tail->_next = new SListNode(x);
		_tail = _tail->_next;
	}
}


template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PopBack()
{
	if (_head == NULL)
	{
		cout << "空单链表 " << endl;
		return;
	}
	SListNode*cur = _head;
	while (cur->_next->_next)
	{
		cur = cur->_next;
	}
	_tail = cur;
	delete cur->_next;
	_tail->_next = NULL;
}

template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PushFront(DataType x)
{
	if (_head == NULL)
	{
		PushBack(x);
	}
	SListNode *temp = new SListNode(x);
	temp->_next = _head;
	_head = temp;
}


template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PopFront()
{
	if (_head == NULL)
	{
		cout << "空链表" << endl;
		return;
	}
	SListNode*temp = _head;
	_head = _head->_next;
	delete temp;
}

//template<class DataType, class SListNode = SListNode<DataType> >
//void SList<DataType, SListNode>::Insert(const SListNode* pos, DataType x)
//{
//	if (_head == NULL)
//	{
//		cout << "空链表!" << endl;
//		return;
//	}
//	SListNode *cur = _head;
//	while (cur)
//	{
//		if (cur == pos)
//		{
//			SListNode*temp = new SListNode(x);
//			temp->_next = pos->_next;
//			pos->_next = temp;
//			return;
//		}
//		cur = cur->_next;
//	}
//	cout << "链表中未找到此节点!" << endl;
//}

下边给出输出函数

template<class DataType, class SListNode = SListNode<DataType> >
void SList<DataType, SListNode>::PrintSList()
{
	SListNode*cur = _head;
	while (cur)
	{
		cout << cur->_data << "->";
		cur = cur->_next;
	}
	cout << "NULL" << endl;
}

上边就是主要的函数声明与定义了,单链表内容也是很多的,用作举例,我认为上述的函数就够用了,下边给出测试函数:

#include"SList.h"

void test5()
{
	cout << "使用 int 类型构造 :" << endl;
	cout << "s1:" << endl;
	SList<int> s1;
	s1.PushBack(1);
	s1.PushBack(2);
	s1.PushBack(3);
	s1.PushBack(4);
	s1.PushBack(5);
	s1.PrintSList();
	cout << "拷贝构造 s2:" << endl;
	SList<int> s2(s1);
	s2.PopBack();
	s2.PrintSList();

	cout << "赋值运算符重载 s3:" << endl;
	SList<int> s3;
	s3 = s1;
	s3.PopFront();
	s3.PrintSList();
}

void test6()
{
	cout << "使用 char 类型构造 :" << endl;
	cout << "s1:" << endl;
	SList<char> s1;
	s1.PushBack('a');
	s1.PushBack('b');
	s1.PushBack('c');
	s1.PushBack('d');
	s1.PushBack('e');
	s1.PrintSList();
	cout << " 拷贝构造  s2:" << endl;
	SList<char> s2(s1);
	s2.PopBack();
	s2.PrintSList();

	cout << "赋值运算符重载  s3:" << endl;
	SList<char> s3;
	s3 = s1;
	s3.PopFront();
	s3.PrintSList();
}

void test7()
{
	cout << "使用 string 类型构造 :" << endl;
	cout << "s1:" << endl;
	SList<string> s1;
	s1.PushBack("xxxx");
	s1.PushBack("ssss");
	s1.PushBack("aaaa");
	s1.PushBack("dddd");
	s1.PushBack("eeee");
	s1.PrintSList();
	cout << "拷贝构造  s2:" << endl;
	SList<string> s2(s1);
	s2.PopBack();
	s2.PrintSList();

	cout << "赋值运算符重载  s3:" << endl;
	SList<string> s3;
	s3 = s1;
	s3.PopFront();
	s3.PrintSList();
}

int main()
{
	test5();
	test6();
	test7();

	system("pause");
	return 0;
}

在测试函数里主要测试了基本类型中的int char类型以及非基本类型中的string类型,使用了构造函数、析构函数、赋值运算符重载、插入删除操作,结果如下图

wKiom1bq0RzjUpTJAAAkTnjTPIA168.png

限于我目前的c++水平 仅能实现上述函数,欢迎大家阅读,如发现错误或者不足,恳请您给予批评指正,谢谢!

本文出自 “分享中进步” 博客,请务必保留此出处http://xmwen1.blog.51cto.com/10730069/1752368

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象程序设计课程作业 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、付费专栏及课程。

余额充值