C++实现单链表

单链表的结构有多种

这里介绍的链表有头结点、有尾节点并且尾节点指向头结点

SList.h

//****************/

typedef int DataType;

//节点类(复合形态)
//struct LinkNode     
//{
//	friend class SList;      //将SList设为友元,便于SList类可以访问节点类的私有成员
//public:
//	LinkNode(const DataType x);	
//private:
//	DataType _data;    //节点的数据
//	LinkNode* _next;    //指向该节点的下一个节点
//};

//直接用struct定义LinkNode类,因为struct的成员默认为公有数据成员,所以可直接访问
struct LinkNode      //节点类(建议写法)
{
	LinkNode(const DataType x);
	DataType _data;    //节点的数据
	LinkNode* _next;    //指向该节点的下一个节点
};
class SList
{
public:
	SList();         //构造函数
	SList(const SList& s);        //拷贝构造
	SList &operator=(SList& s);    //赋值运算符的重载
	~SList();

public:   //单链表的具体操作
	void Reverse();   //翻转
	void Swap(SList& s);      
	void PrintSList();   //打印链表
	void PushBack(const DataType& x);    //在尾部插入一个节点
	void Clear();         //链表置空
	void PopBack();       //删除尾节点
	void PushFront(DataType x);  //头插
	void PopFront();    //删除首节点
	void Insert(LinkNode* pos, DataType x);//固定位置插入一个节点
	void Erase(LinkNode* pos);        //删除某一节点
	LinkNode* Find(DataType x);       //查找节点并返回这个节点的地址
	int Amount();   //计算链表节点的数目
	void Remove(DataType x);     //查找某节点并删除
	void RemoveAll(DataType x);      //删除链表中所有的x
	
private:	
	LinkNode* _head;     //指向头节点
	LinkNode* _tail;        //指向尾节点
};
//*********************//

SList.cpp   (函数实现)

//**********************/////////
#include<iostream>
using namespace std;
#include<assert.h>
#include"SList.h"

   LinkNode::LinkNode(const DataType x)
           :_data(x)
           , _next(NULL)
           {}

    SList::SList()         //构造函数
		:_head(NULL)
		, _tail(NULL)
	{}
	SList::SList(const SList& s)          //拷贝构造
		:_head(NULL)
		, _tail(NULL)
	{
		if (s._head == NULL)
		{
			return;
		}
		LinkNode* tmp = s._head;
		do{
			PushBack(tmp->_data);
			tmp = tmp->_next;
		    } while (tmp != s._head);
		
	}
    //赋值运算符的重载(传统方法)
	//SList & SList::operator=(const SList& s)    
	//{
	//	if (this != &s)
	//	{
	//		_head = NULL;
	//		_tail = NULL;
	//		LinkNode* tmp = s._head;
	//	do{
	//		PushBack(tmp->_data);
	//		tmp = tmp->_next;
	//	     } while (tmp != s._head);
	//	}
	//	return *this;	
	//}
    
	//赋值运算符的重载(高效写法)
	/*void SList::Swap(SList& s)     
	{
	swap(_head, s._head);
	swap(_tail, s._tail);

	}
	SList&  SList::operator=(SList &s)
	{
	if (this != &s)
	{
	SList tmp(s);
	Swap(tmp);
	}
	return *this;
	}*/

	SList&  SList::operator=(SList &s)     //赋值运算符的重载再优化(推荐写法)
	{
		if (this != &s)
		{
			swap(_head, s._head);
			swap(_tail, s._tail);
		}
		return *this;
	}
	SList::~SList()    //析构
	{
		Clear();
	}

        void SList::Reverse()   //链表逆置(利用头插新节点的方法)
	{
		if (_head == NULL||_head->_next==_tail)
		{
			return;
		}
		int ret = Amount();
		_tail = new LinkNode(_head->_data);
		LinkNode* begin=NULL;
		LinkNode* tmp = _tail;
		while (--ret)
		{
			LinkNode* del = _head;
			_head = _head->_next;
			delete del;	//这里不要忘记做清理工作,否则内存泄漏
			begin = new LinkNode(_head->_data);
			begin->_next = tmp;
			_tail->_next = begin;
		    tmp = begin;
		}
		_head = begin;
	}  

        //打印链表
	void SList::PrintSList()  
	{
		//头结点为空时,无需打印链表
		if (_head==NULL)
		{
			cout << "This SList is Empty !" << endl;
			return;
		}
		else
		{
			LinkNode* tmp = _head;
			do{ 
				cout << tmp->_data << "-->";
				tmp = tmp->_next;
			    } while (tmp != _head);
			cout << endl;
		}
	}
	void SList::PushBack(const DataType& x)    //在尾部插入一个节点
	{
		//如果链表为空,插入节点后只有一个节点,此时_head=_tail
		if (_head == NULL)
		{
			_head = new LinkNode(x);
			_tail = _head;
			_tail->_next = _head;
		}
		else
		{
			_tail->_next = new LinkNode(x);
			_tail = _tail->_next;
			_tail->_next = _head;
		}
	}
	void SList::Clear()         //链表置空
	{
		LinkNode* begin = _head;
		while (begin != _tail)
		{
			_head = _head->_next;
			delete begin;
			begin = _head;
		}
		_head = NULL;
		_tail = NULL;
	}
	void SList::PopBack()    //尾删
	{
		if (_head == NULL)
		{
			cout << "This SList is empty !" << endl;
		}
		else if (_head == _tail)
		{
			delete _head;
			_head = NULL;
			_tail = NULL;
		}
		else
		{
			LinkNode* cur = _head;
			while (cur->_next != _tail)
			{
				cur = cur->_next;
			}
			delete _tail;
			_tail = cur;
			_tail->_next = _head;
	     }
	}
	void SList::PushFront(DataType x)  //头插
	{
		if (_head == NULL)
		{
			PushBack(x);
		}
		else
		{
			LinkNode* tmp = _head;
			_head = new LinkNode(x);
			_head->_next = tmp;
			_tail->_next = _head;
		}
	}
	void SList::PopFront()    //删除首节点
	{
		if (_head == NULL)
		{
			cout << "This SList is empty !" << endl;
			return;
		}
		LinkNode* tmp = _head;
		_head = _head->_next;
		_tail->_next = _head;
		delete tmp;
	}

	//固定位置插入一个节点(这个函数需和Find函数搭配使用)
	//先用Find函数找到新节点需要插入的位置
	//(将Find函数的返回值传给Insert函数的参数pos),再在pos节点后面插入新节点x
	void SList::Insert(LinkNode* pos, DataType x)
	{
		assert(pos);
		if (pos==_tail)
		{
			PushBack(x);
		}
		else
		{
			LinkNode* tmp = new LinkNode(x);
			tmp->_next = pos->_next;
			pos->_next = tmp;
		}
	}
	
        //删除某一节点,同样,要先找到该节点并传参给Erase函数
	void SList::Erase(LinkNode* pos)        
	{
		assert(pos);
		if (pos == _tail)
		{
			PopBack();
		}
		if (pos == _head)
		{
			PopFront();
		}
		else
		{
			LinkNode* prev = _head;
			while (prev->_next != pos)
			{
				prev = prev->_next;
			}
			prev->_next = pos->_next;
			delete pos;
		}
	}
	LinkNode* SList::Find(DataType x)       //查找节点并返回这个节点的地址
	{
		if (_head == NULL)
		{
			cout << "This SList is empty !" << endl;
			return NULL;
		}
		else
		{
			LinkNode* tmp = _head;
			do{
					if (tmp->_data == x)
					{
						return tmp;
					}
						tmp = tmp->_next;
			} while (tmp != _head);
			return NULL;
		}
	}
	int SList::Amount()   //计算链表节点的数目
	{
		if (_head == NULL)
		{
			return 0;
		}
		else
		{
			int count = 0;
			LinkNode* cur = _head;
			while (cur != _tail)
			{
				count++;
				cur = cur->_next;
			}
			return ++count;
		}
	}
	void SList::Remove(DataType x)      //查找某节点并删除
	{
		if (_head == NULL)
		{
			cout << "This SList is empty !" << endl;
		}
		else
		{
			LinkNode* tmp = Find(x);
			if (tmp != NULL)
			{
				Erase(tmp);
			}
		}
	}
	void SList::RemoveAll(DataType x)       //删除链表中所有的x
	{
		if (_head == NULL)
		{
			cout << "This SList is empty !" << endl;
			return;
		}
//如果链表不为空,设置left和right前后指针,从头至尾遍历一遍,delete节点的data为x的节点

			LinkNode* left = _tail;
			LinkNode* right = _head;
			int count = Amount();
			while (count--)
			{
			 //当要删掉的节点是头节点时,需要注意头节点要指向它的下一个节点
			 //当要删掉的节点是尾节点时,需要注意尾节点要指向它的上一个节点
			 //当left和right指向同一块要删掉的节点时,将链表置空
			 
				if (right->_data == x)
				{
					if (_head == right)   
					{
						_head = _head->_next;
					}
					if (_tail == right)   
					{
						_tail =left;
					}
					if (right == left)    
					{
						_head = NULL;
						_tail = NULL;
						return;
					}
					LinkNode* tmp = right;
					right = right->_next;
					delete tmp;
					left->_next = right;
				}
				else
				{
					left = right;
					right = right->_next;
				}
			}	
	}
///************************

测试用例(Test.cpp)

#include"SList.h"
#include<stdlib.h>

void Test2()
{
	SList list1;
	list1.PushBack(1);
	list1.PushBack(3);
	list1.PushBack(4);
	list1.PushBack(2);
	list1.PushBack(6);
	list1.PrintSList();

	/*list1.RemoveAll(2);
	list1.PrintSList();*/

	SList list2 = list1;
	/*list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(2);
	list2.PushBack(2);*/
	list2.PrintSList();
	list2.Reverse();
	list2.PrintSList();
	
}
void Test1()
{
	//SList list1;
	//list1.PushBack(1);
	//list1.PushBack(2);
	//list1.PushBack(3);
	//list1.PushBack(4);
	//list1.PushBack(5);
	//list1.PrintSList();

	//list1.Remove(2);
	//list1.PrintSList();

	//int num =list1.Amount();
	//cout <<"节点个数:"<< num << endl;

	/*//检验Erase函数
	LinkNode* del = list1.Find(2);
	list1.Erase(del);
	list1.PrintSList();
	*/

	/*//找到某节点并在其后插入新节点
	LinkNode* In =list1.Find(5);
	list1.Insert(In, 0);
	list1.PrintSList();*/

	/* //删除头结点
	list1.PopFront();
	list1.PrintSList();
	*//////

	/*//////查找节点
	LinkNode* ret=list1.Find(5);
	if (ret != NULL)
	{
	cout << "要查找的节点data是:" << ret->_data << endl;
	cout << "要查找的节点adress是:" <<ret<< endl;
	}
	else
	{
	cout << "not exit !" << endl;
	}*////////

	//验证构造函数
	//SList list2(list1);
	//list2.PrintSList();

	//验证赋值运算符的重载
	//SList list3 = list2;
	//list3.PrintSList();

	//验证析构函数
	//list3.Clear();
	//list3.PrintSList();

	//验证尾删和头插
	///*list3.PopBack();
	//list3.PrintSList();*/
	//list3.PushFront(0);
	//list3.PrintSList();
}

int main()
{
	//Test1();
	Test2();
	system("pause");
}


本文出自 “言安阳” 博客,谢绝转载!

你可能感兴趣的:(C++,类,单链表)