链表和链表类模板

1、链表

设计一个简单的单项链表。链表的功能包括向尾节点添加数据、遍历链表中的节点和在链表结束时释放所有节点。

定义一个链表类

class cnode                            //定义一个节点类
{
public:
	cnode *m_pnext;                    //定义一个节点指针,指向下一个节点
	int m_data;                        //定义节点的数据
	cnode()
	{
		m_pnext=NULL;                  //将m_pnext设置为空
	}
};


class clist                            //定义链表类clist类
{
private:
	cnode *m_pheader;                  //定义头节点
	int m_nodesum;                     //定义节点数量
public:
	clist()                            //定义链表的构造函数
	{
		m_pheader=NULL;                //初始化m_pheader
		m_nodesum=0;                   //初始化m_nodesum
	}
	cnode *movetrail()                 //移动到尾节点
	{
		cnode *ptmp=m_pheader;         //定义一个临时节点,将其指向头节点
		for(int i=1;i<m_nodesum;i++)   //遍历节点
			ptmp=ptmp->m_pnext;        //获取下一个节点
		return ptmp;                   //返回尾节点
	}
	void addnode(cnode *pnode)         //添加节点
	{
		if(m_nodesum==0)               //判断链表是否为空
			m_pheader=pnode;           //将节点添加到头节点中
		else                           //链表不为空
		{
			cnode *ptrail=movetrail(); //搜索尾节点
			ptrail->m_pnext=pnode;     //在尾节点处添加节点
		}
		m_nodesum++;                   //使链表节点数量加1
	}
	void passlist()                    //遍历列表
	{
		if(m_nodesum>0)                //判断链表是否为空
		{
			cnode *ptmp=m_pheader;           //定义一个临时节点,将其指向头节点
			printf("%4d",ptmp->m_data);     //输出节点数据
			for(int i=1;i<m_nodesum;i++)    //遍历其他节点
			{
				ptmp=ptmp->m_pnext;         //获取下一个节点
				printf("%4d",ptmp->m_data); //输出节点数据
			}
		}
	}
	~clist()                                 //定义链表析构函数
	{
		if(m_nodesum>0)                      //链表不为空
		{
			cnode *pdelete=m_pheader;        //定义一个临时节点,指向头节点
			cnode *ptmp=NULL;                //定义一个临时节点
			for(int i=0;i<m_nodesum;i++)     //遍历节点
			{
				ptmp=pdelete->m_pnext;       //获取下一个节点
				delete pdelete;              //释放当前节点
				pdelete=ptmp;                //将下一个节点设置为当前节点
			}
			m_nodesum=0;                     //将m_nodesum设置为0
			pdelete=NULL;                    //将pdelete设置为空
			ptmp=NULL;                       //将ptmp设置为空
		}
		m_pheader=NULL;                      //将m_pheader设置为空
	}
};

声明一个链表对象,向其中添加节点,并遍历链表节点

void main()
{
	clist list;                             //定义链表对象
	for(int i=0;i<5;i++)                    //利用循环向列表中添加5个节点
	{
		cnode *pnode=new cnode();           //构造节点对象
		pnode->m_data=i;                    //设置节点数据
		list.addnode(pnode);                //添加节点到链表
	}
	list.passlist();                        //遍历节点
	cout<<endl;                             //输出换行
}

结果如下:

链表和链表类模板

2、链表类模板

使用类模板让链表类clist能够适应各种类型的节点,在原来链表的基础上将链表中出现的cnode类型的地方替换为模板参数type

 

template <class type>

class clist                            //定义clist类
{
private:
	type *m_pheader;                   //定义头节点
	int m_nodesum;                     //定义节点数量
public:
	clist()                            //定义构造函数
	{
		m_pheader=NULL;                //初始化m_pheader
		m_nodesum=0;                   //初始化m_nodesum
	}
	type *movetrail()                 //移动到尾节点
	{
		type *ptmp=m_pheader;         //定义一个临时节点,将其指向头节点
		for(int i=1;i<m_nodesum;i++)   //遍历节点
			ptmp=ptmp->m_pnext;        //获取下一个节点
		return ptmp;                   //返回尾节点
	}
	void addnode(type *pnode)         //添加节点
	{
		if(m_nodesum==0)               //判断链表是否为空
			m_pheader=pnode;           //将节点添加到头节点中
		else                           //链表不为空
		{
			type *ptrail=movetrail(); //搜索尾节点
			ptrail->m_pnext=pnode;     //在尾节点处添加节点
		}
		m_nodesum++;                   //使链表节点数量加1
	}
	void passlist()                    //遍历列表
	{
		if(m_nodesum>0)                //判断链表是否为空
		{
			type *ptmp=m_pheader;           //定义一个临时节点,将其指向头节点
			printf("%4d",ptmp->m_data);     //输出节点数据
			for(int i=1;i<m_nodesum;i++)    //遍历其他节点
			{
				ptmp=ptmp->m_pnext;         //获取下一个节点
				printf("%4d",ptmp->m_data); //输出节点数据
			}
		}
	}
	~clist()                                 //定义析构函数
	{
		if(m_nodesum>0)                      //链表不为空
		{
			type *pdelete=m_pheader;        //定义一个临时节点,指向头节点
			type *ptmp=NULL;                //定义一个临时节点
			for(int i=0;i<m_nodesum;i++)     //遍历节点
			{
				ptmp=pdelete->m_pnext;       //获取下一个节点
				delete pdelete;              //释放当前节点
				pdelete=ptmp;                //将下一个节点设置为当前节点
			}
			m_nodesum=0;                     //将m_nodesum设置为0
			pdelete=NULL;                    //将pdelete设置为空
			ptmp=NULL;                       //将ptmp设置为空
		}
		m_pheader=NULL;                      //将m_pheader设置为空
	}
};

在定义节点类

class cnet                                   //定义一个节点类
{
public:
	cnet *m_pnext;                           //定义一个节点指针
	char m_data;                             //定义节点类的数据成员
	cnet()                                   //定义构造函数
	{
		m_pnext=NULL;                        //将m_pnext设置为空
	}
};


class cnode                                  //定义一个节点类
{
public:
	cnode *m_pnext;                          //定义一个节点指针
	int m_data;                              //定义节点类的数据
	cnode()
	{
		m_pnext=NULL;                        //将m_pnext设置为空
	}
};

构造类模板实例

    clist<cnode>nodelist;                   //构造一个类模板实例
	for(int n=0;n<5;n++)                    //利用循环向链表中添加节点
	{
		cnode *pnode=new cnode();           //创造节点对象
		pnode->m_data=n;                    //设置节点数据
		nodelist.addnode(pnode);            //向链表中添加节点
	}
	nodelist.passlist();                    //遍历列表
	cout<<endl;                             //输出换行
	clist<cnet>netlist;                     //构造一个类模板实例
	for(int i=0;i<5;i++)                    //利用循环向链表中添加节点
	{
		cnet*pnode=new cnet();              //创造节点对象
		pnode->m_data=10+i;                 //设置节点数据
		netlist.addnode(pnode);             //向链表中添加节点
	}
	netlist.passlist();                     //遍历列表
	cout<<endl;                             //输出换行

结果如下

链表和链表类模板

类模板clist虽然能使用不同类型的节点,但是对节点的类型是有一定要求的。

(1)、节点类必须包含一个指向自身的指针类型成员m_pnext,因为clist中访问了m_pnext成员

(2)、节点中必须包含数据成员m_data,其类型被限制为数字类型或有序类型 

上一篇:1189:Pell数列


下一篇:STM32CubeIDE系列教程-13SPI通信