1. 程式人生 > >【C++】模板類連結串列

【C++】模板類連結串列

上一篇部落格介紹了模板類順序表,此篇部落格主要是模板類連結串列的實現。

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

template<typename T>
struct Node
{
public:
	Node(const T&x)
		:_data(x), _next(NULL), _prev(NULL)
	{}
	T _data;
	Node<T>*_next;
	Node<T>*_prev;
};


template<typename T>
class LinkList
{
	template<typename T>
	friend ostream&operator<<(ostream&os, const LinkList<T>&list);
public:
	LinkList()
		:_head(NULL), _tail(NULL), _sz(0)
	{}

	~LinkList()
	{
		Release();
	}
	LinkList(const LinkList<T>&list);   //拷貝構造
	void PushBack(T x);  //尾插
	void PopBack();   //尾刪
	void PushFront(T x);  //頭插
	void PopFront();  //頭刪
	Node<T>* Find(T x);      //查詢指定元素的地址
	void Insert(Node<T>* node, T x); //指定位置插入指定資料
	void Remove(T x);     //刪除指定元素
	void RemoveAll(T x);  //刪除連結串列裡出現的所有指定資料
	void Erase(Node<T>* node);      //指定位置刪除
	void BubbleSort();           //氣泡排序
	int& GetSz()
	{
		return _sz;
	}
public:
	void Release()
	{
		Node<T>* cur = _head;
		while (cur)
		{
			Node<T>*tmp = cur;
			cur = cur->_next;
			delete tmp;
			tmp = NULL;
		}
		_head = NULL;
		_tail = NULL;
		_sz = 0;
	}
	Node<T>*_head;
	Node<T>*_tail;
	int _sz;
};
template<typename T>
ostream&operator<<(ostream&os, const LinkList<T>&list)
{
	Node<T>*cur = list._head;
	while (cur)
	{
		os << cur->_data << "-";
		cur = cur->_next;
	}
	cout << "end" << endl;
	return os;
}

template<typename T>
LinkList<T>::LinkList(const LinkList<T>&list)
{
	Node<T>* cur = list._head;
	while (cur)
	{
		PushBack(cur->_data);
		_sz++;
		cur = cur->_next;
	}
}
template<typename T>
void LinkList<T>::PushBack(T x)
{
	Node<T>* node = new Node<T>(x);
	if (NULL == _head)
	{
		_head = node;
		_tail = node;
	}
	else
	{
		_tail->_next = node;
		node->_prev = _tail;
		_tail = node;
	}
	_sz++;
}

template<typename T>
void LinkList<T>::PopBack()   //尾刪
{
	if (NULL == _head)
	{
		throw string("no data in list");
	}
	else if (NULL == _head->_next)
	{
		Release();
	}
	else
	{
		_tail = _tail->_prev;
		delete _tail->_next;
		_tail->_next = NULL;
		_sz--;
	}
}

template<typename T>
void LinkList<T>::PushFront(T x)  //頭插
{
	Node<T>*NewNode = new Node<T>(x);
	if (NULL == _head)
	{
		_head = NewNode;
		_tail = NewNode;
	}
	else
	{
		NewNode->_next = _head;
		_head->_prev = NewNode;
		_head = NewNode;
	}
	_sz++;
}

template<typename T>
void LinkList<T>::PopFront()  //頭刪
{
	if (NULL == _head)
	{
		throw string("no data in list");
	}
	else if (NULL == _head->_next)
	{
		Release();
	}
	else
	{
		_head = _head->_next;
		delete _head->_prev;
		_head->_prev = NULL;
		_sz--;
	}
}

template<typename T>
Node<T>* LinkList<T>::Find(T x)      //查詢指定元素的地址
{
	Node<T>* cur = _head;
	while (cur)
	{
		if (cur->_data == x)
		{
			return cur;
		}
		cur = cur->_next;
	}
	return NULL;
}

template<typename T>
void LinkList<T>::Insert(Node<T>* node, T x) //指定位置插入指定資料
{
	Node<T>* cur = _head;
	Node<T>* NewNode = new Node<T>(x);
	if (node == _head)
	{
		PushFront(x);
	}
	else
	{
		while (cur)
		{
			if (cur == node)
			{
				NewNode->_next = cur;
				NewNode->_prev = cur->_prev;
				cur->_prev = NewNode;
				NewNode->_prev->_next = NewNode;
				_sz++;
			}
			cur = cur->_next;
		}
	}
}

template<typename T>
void LinkList<T>::Remove(T x)     //刪除指定元素
{
	Node<T>*cur = _head;
	if (_head->_data == x)
	{
		PopFront();
	}
	else
	{
		while (cur && (cur->_data != x))
		{
			cur = cur->_next;
		}
		if (cur == NULL)
		{
			cout << "no such data" << endl;
		}
		else
		{
			cur->_prev->_next = cur->_next;
			cur->_next->_prev = cur->_prev;
			cur->_next = NULL;
			cur->_prev = NULL;
			delete cur;
			_sz--;
		}
	}
}

template<typename T>
void LinkList<T>::RemoveAll(T x) //刪除連結串列裡出現的所有指定資料
{
	Node<T>*cur = _head;
	while (cur)
	{
		if ((cur->_data == x) && (cur->_next != NULL) && (cur->_prev != NULL))
		{
			Node<T> *del = cur;
			cur = cur->_next;
			del->_prev->_next = del->_next;
			del->_next->_prev = del->_prev;
			del->_next = NULL;
			del->_prev = NULL;
			delete del;
			_sz--;
		}
		else if ((cur->_data == x) && (cur->_next == NULL))
		{
			//PopBack();
			_tail = cur->_prev;
			cur->_prev = NULL;
			_tail->_next = NULL;
			delete cur;
			cur = NULL;
		}
		else if ((cur->_data == x) && (cur->_prev == NULL))
		{
			//PopFront();
			Node<T>*del = cur;
			cur = cur->_next;
			_head = _head->_next;
			_head->_prev = NULL;
			del->_next = NULL;
			delete del;
			del = NULL;
		}
		else
			cur = cur->_next;
	}
}

template<typename T>
void LinkList<T>::Erase(Node<T>* node)      //指定位置刪除
{
	Node<T>* cur = _head;
	while (cur)
	{
		if ((cur == node) && (cur->_next != NULL) && (cur->_prev != NULL))
		{
			Node<T> *del = cur;
			cur = cur->_next;
			del->_prev->_next = del->_next;
			del->_next->_prev = del->_prev;
			del->_next = NULL;
			del->_prev = NULL;
			delete del;
			_sz--;
		}
		else if ((cur == node) && (cur->_next == NULL))
		{
			_tail = cur->_prev;
			cur->_prev = NULL;
			_tail->_next = NULL;
			delete cur;
			cur = NULL;
		}
		else if ((cur == node) && (cur->_prev == NULL))
		{
			//PopFront();
			Node<T>*del = cur;
			cur = cur->_next;
			_head = _head->_next;
			_head->_prev = NULL;
			del->_next = NULL;
			delete del;
			del = NULL;
		}
		else
			cur = cur->_next;
	}
}

template<typename T>
void LinkList<T>::BubbleSort()           //氣泡排序
{
	Node<T>* cur = _head;
	Node<T>* EndOk = NULL;
	while (cur->_next)
	{
		Node<T>*incur = _head;
		while (incur->_next != EndOk)
		{
			if (incur->_data > incur->_next->_data)
			{
				T tmp = incur->_data;
				incur->_data = incur->_next->_data;
				incur->_next->_data = tmp;
			}
			incur = incur->_next;
		}
		EndOk = incur;
		cur = cur->_next;
	}
}


void test1()
{
	LinkList<int>list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	//LinkList<int>list1(list);
	cout << list << endl;
	list.PopBack();
	cout << list << endl;
	list.PopBack();
	cout << list << endl;
	list.PopBack();
	cout << list << endl;
	try
	{
		list.PopBack();
	}
	catch (string e)
	{
		cout << e << endl;
	}
	cout << list << endl;
	try
	{
		list.PopBack();
	}
	catch (string e)
	{
		cout << e << endl;
	}
	cout << list << endl;
}

void test2()
{
	LinkList<int> list;
	list.PushFront(1);
	list.PushFront(2);
	list.PushFront(3);
	cout << list << endl;
	try{ list.PopFront(); }
	catch (string e)
	{
		cout << e << endl;
	}
	cout << list << endl;
	try{ list.PopFront(); }
	catch (string e)
	{
		cout << e << endl;
	}
	cout << list << endl;
	try{ list.PopFront(); }
	catch (string e)
	{
		cout << e << endl;
	}
	cout << list << endl;
	try{ list.PopFront(); }
	catch (string e)
	{
		cout << e << endl;
	}
	cout << list << endl;
}

void test3()
{
	LinkList<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	cout << list << endl;
	Node<int>* ret = list.Find(3);
	list.Insert(ret, 9);
	cout << list << endl;
	LinkList<string> list1;
	list1.PushBack("ajffas");
	list1.PushBack("adgadgagasdjga");
	cout << list1 << endl;
	LinkList<string> list2(list1);
	cout << list2 << endl;
}

void test4()
{
	LinkList<int> list;
	list.PushBack(2);
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(2);
	list.PushBack(2);
	cout << list << endl;
	/*list.Remove(2);
	cout << list << endl;*/
	list.RemoveAll(2);
	cout << list << endl;
}

void test5()
{
	LinkList<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	cout << list << endl;
	/*Node<int>*ret = list.Find(2);
	list.Erase(ret);*/
	cout << list << endl;
}

void test6()
{
	LinkList<int> list;
	list.PushFront(1);
	list.PushFront(2);
	list.PushFront(3);
	list.PushFront(4);
	cout << list << endl;
	list.BubbleSort();
	cout << list << endl;
}
     當然,模板也有利弊,雖然它複用了程式碼,節省資源,可以更快的迭代開發,增強了程式碼的靈活性。但是模板讓程式碼變得錯綜複雜,不易維護,編譯程式碼時間變長。而且,當出現錯誤時,錯誤資訊非常凌亂,親自感受一下就能知道,每次發生一個錯誤,真的要好久才能找到錯在哪裡,不易定位錯誤。