www.gusucode.com > 《C++高级语言程序设计》PPT及全书例子源代码-源码程序 > 《C++高级语言程序设计》PPT及全书例子源代码-源码程序/code/C++例题程序/第5章/s5_6/smain5_6.cpp

    //Download by http://www.NewXing.com
//主文件
//文件名:s5_6\smain5_6.cpp
//类声明及实现文件,对类模板,类的声明和实现放在同一个文件中

//编译预处理语句:如果未定义__SCLASS5_6_T_H__则定义它,
//直到遇到#endif结束

#ifndef __SCLASS5_6_T_H__ 
#define __SCLASS5_6_T_H__ 

#include <iostream>  		//包含头文件。使用iostream库

using namespace std; 		//使用std命名空间

//定义链表的结点结构类
class SNode
{

public:
	SNode( int value );
	~SNode( ){ };
	
	//公有数据,方便后面取值
	int m_value;		//结点值
	SNode *m_next;		//结点后继,指向下一个结点的指针
};

//定义链表的类模板
template <class Type>
class TList
{
public:
	TList( );						//构造函数
	~TList( );						//析构函数

	virtual bool Insert( Type value );	//在链表头部插入一个结点
	bool Delete( Type value );			//从链表中删除值为value的一个结点
	bool Contain( Type value );			//判断链表中是否包含某结点
	void Print( );					//输出链表结点的值
protected:
	SNode *m_head;					//设置为只有头指针的单向链表
};

//定义集合类模板--集合与链表采用同样的组织方式,如图5.1所示
//但是链表和集合德概念不同:集合中不允许有重复的结点
template<class Type>
class TSet : public TList<Type>
{
public:
	bool Insert( Type value );	//在集合中重载插入方法,插入前先判断结点是否已经存在
};

#endif   					//结束编译预处理 

//结点类构造函数
SNode::SNode( int value )
{
	m_value = value;			//结点值
	m_next = NULL;				//结点后继
}

//构造函数
template <class Type>
TList<Type>::TList( )
{
	m_head = NULL;			//链表头
}

//链表析构函数。在析构函数中需要delete所有还在链表中的结点
template <class Type>
TList<Type>::~TList( )
{
	SNode *p = m_head;			//
	for (  ; p != NULL;  )		//直到结点不为空
	{
		m_head = p->m_next;		//头结点指向下一个结点,作为新的头结点
		delete p;				//释放p所指向的结点
		p = m_head;			//p指向新的头结点
	}
}

//在链表头部插入
template <class Type>
bool TList<Type>::Insert( Type value )
{
	SNode  *pTemp = new SNode( value );		//构造一个新结点
	if ( pTemp == NULL )					//结点空间申请不成功,退出
	{
		return false;
	}
	
	pTemp->m_next = m_head;		//新结点的m_next指针指向头结点原来所指的结点
	m_head = pTemp;				//头结点改为新生成的结点
	return true;
}

template <class Type>
bool TList<Type>::Delete( Type value )
{
	SNode *p1, *p2;		//申请两个结点指针,用于结点操作时
	//要遍历整个链表以查找其中是否包含有结点值为value的结点
	//但是一次遍历只能够删除一个值为value的结点。
	//如果在链表中有多个值相同的结点,需要分别删除。
	if ( m_head->m_value == value )		//如果头结点就是要找的结点,直接删除
	{
		p1 = m_head->m_next;			//p1指向头结点的后继结点
		delete m_head;				//释放头结点
		m_head = p1;				//p1成为新的头结点,即原头结点的后继成为新的头结点
		return true;				//返回真
	}
	else							//要删除的结点非头结点
	{
		for ( p1 = m_head, p2 = m_head->m_next; p2 != NULL;   )//遍历链表
		{
			if ( p2->m_value == value )		//如果找到,则释放该结点,并结束遍历
			{
				p1->m_next = p2->m_next;	//p1指向p2的下一个结点
				delete p2;				//释放p2
				p2 = NULL;				//让p2指向NULL,该步骤通常很有必要
				return true;				//结束遍历。
			}
			else						//如果该结点不是要找的结点,则p1,p2向后遍历
			{
				p1 = p1->m_next;		//p1指向其后继
				p2 = p2->m_next;		//p2指向其后继
			}
		}
	}
	return false;						//没有找到需要的结点,返回false
}

template <class Type>
bool TList<Type>::Contain( Type value )
{
	//遍历链表以查找其中是否包含有结点值为value的结点,有返回true,没有返回false
	for ( SNode  *p = m_head; p != NULL; p = p->m_next )
	{
		if ( p->m_value == value )			//找到该结点,返回true
		{
			return true;
		}
	}
	return false;
}

//显示表中的结点数据
template <class Type>
void TList<Type>::Print( )
{
	cout << "结点的值依次为:";
	//遍历链表以读出每一个结点的值并在终端上显示。
	for ( SNode  *p = m_head; p != NULL; p = p->m_next )
	{
		cout << " " << p->m_value << "; ";      //显示结点值
	}
	cout << endl;								//结束输出流
}


//集合类的结点插入方法
template <class Type>
bool TSet<Type>::Insert( Type value )
{
	//集合中无值为value的结点,才可以作插入操作,否则直接返回false。插入失败也返回false
	if ( !( TList<Type>::Contain( value ) )&&( TList<Type>::Insert( value ) ) )
	{
		return true;
	}
	return false;
}


//主测试程序
void main( )  
{
	TList<int> sIntList;
	sIntList.Insert( 12 );
	sIntList.Insert( 24 );		//在链表sIntList中,两次插入24
	sIntList.Insert( 48 );
	sIntList.Insert( 96 );
	sIntList.Insert( 24 );		//在链表sIntList中,两次插入24
	sIntList.Print( );

	sIntList.Delete( 24 );		//删除一次24
	sIntList.Print( );

	TSet<int> sIntSet;
	sIntSet.Insert( 12 );
	sIntSet.Insert( 24 );		//在集合sIntList中,两次插入24
	sIntSet.Insert( 48 );
	sIntSet.Insert( 96 );
	sIntSet.Insert( 24 );		//在集合sIntList中,两次插入24
	sIntSet.Print( );

	sIntSet.Delete( 24 );		//删除一次24
	sIntSet.Print( );

	cin.get( );
}