码迷,mamicode.com
首页 > 编程语言 > 详细

【C++】双向线性链表容器的实现

时间:2015-08-07 00:26:57      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:c++   stl   list   容器   



// 双向线性链表容器
#include <cstring>
#include <iostream>
#include <stdexcept>
using namespace std;

// 链表类模板
template<typename T>
class List
{
public:
	// 构造、析构、支持深拷贝的拷贝构造和拷贝赋值
	List(void) : m_head(NULL), m_tail(NULL) {}
	~List(void)
	{
		clear();
	}

	List(List const& that) : m_head(NULL), m_tail(NULL)
	{
		for (Node* node = that.m_head; node != NULL;
					node = node->m_next)
			push_back(node->m_data);
	}

	List& operator = (List const& rhs) 
	{
		if (&rhs != this)
		{
			List list(rhs);
			swap(m_head, list.m_head);
			swap(m_tail, list.m_tail);
		}
		return *this;
	}

	// 获取首元素
	T& front(void) 
	{
		if (empty())
			throw underflow_error("链表下溢!");	//下溢异常
		return m_head->m_data;
	}

	T const& front(void) const 
	{
		return const_cast<List*>(this)->front();
	}

	// 向首部压入
	void push_front(T const& data) 
	{
		m_head = new Node(data, NULL, m_head);
		if (m_head->m_next != NULL)
			m_head->m_next->m_prev = m_head;
		else
			m_tail = m_head;
	}

	// 从首部弹出
	void pop_front(void) 
	{
		if (empty())
			throw underflow_error("链表下溢!");
		Node* next = m_head->m_next;
		delete m_head;
		m_head = next;
		if (m_head)
			m_head->m_prev = NULL;
		else
			m_tail = NULL;
	}

	// 获取尾元素
	T& back(void)
	{
		if (empty())
			throw underflow_error("链表下溢!");
		return m_tail->m_data;
	}

	T const& back(void) const 
	{
		return const_cast<List*>(this)->back();
	}
	
	// 向尾部压入
	void push_back(T const& data) 
	{
		m_tail = new Node(data, m_tail);
		if (m_tail->m_prev != NULL)
			m_tail->m_prev->m_next = m_tail;
		else
			m_head = m_tail;
	}

	// 从尾部弹出
	void pop_back(void) 
	{
		if (empty())
			throw underflow_error("链表下溢!");
		Node* prev = m_tail->m_prev;
		delete m_tail;
		m_tail = prev;
		if (m_tail != NULL)
			m_tail->m_next = NULL;
		else
			m_head = NULL;
	}

	// 删除所有匹配元素
	void remove(T const& data) 
	{
		for (Node* node = m_head, *next; node != NULL; 
				node = next)
		{
			next = node->m_next;
			if (equal(data, node->m_data))
			{
				if (node->m_prev != NULL)
					node->m_prev->m_next = node->m_next;
				else
					m_head = node->m_next;

				if (node->m_next)
					node->m_next->m_prev = node->m_prev;
				else
					m_tail = node->m_prev;

				delete node;
			}
		}
	}

	// 清空
	void clear(void) 
	{
		while (!empty())
			pop_back();
	}

	// 判空
	bool empty(void) const 
	{
		return NULL == m_head &&  NULL == m_tail;
	}

	// 大小
	size_t size(void) const 
	{
		size_t nodes = 0;
		for (Node* node = m_head; node != NULL;
				node = node->m_next)
			++nodes;
		return nodes;
	}

	// 下标运算符————SHIT!
	T& operator[] (size_t i)
	{
		for (Node* node = m_head; node != NULL;
				node = node->m_next)
			if (0 == i--)
				return node->m_data;
		throw out_of_range("下标越界!");
	}

	T const& operator[] (size_t i) const
	{
		return const_cast<List&>(*this)[i];
	}

	// 插入输出流
	friend ostream& operator << (ostream& os, 
				List const& list) 
	{
		for (Node* node = list.m_head; node != NULL;
				node = node->m_next)
			os << *node;
		return os;
	}

private:
	// 节点类模板
	class Node
	{
	public:
		Node(T const& data, Node* prev = NULL, Node* next = NULL)
			: m_data(data), m_prev(prev), m_next(next) {}
		friend ostream& operator << (ostream& os, Node const& node)
		{
			return os << '[' << node.m_data << ']';
		}
		T	  m_data;	// 数据
		Node* m_prev;	// 前指针
		Node* m_next;	// 后指针
	};

	// 判断元素是否相等
	bool equal(T const & a, T const& b) const
	{
		return a == b;
	}

	Node* m_head;	// 头指针
	Node* m_tail;	// 尾指针
public:
	// 正向迭代器
	class Iterator
	{
	public:
		Iterator(Node* head = NULL, Node* tail = NULL, Node* node = NULL) 
			: m_head(head), m_tail(tail), m_node(node) {}
		bool operator == (Iterator const& rhs) const
		{
			return m_node == rhs.m_node;
		}

		bool operator != (Iterator const& rhs) const
		{
			return ! (*this == rhs);
		}

		Iterator& operator++ (void)
		{
			if (m_node)
				m_node = m_node->m_next;
			else
				m_node = m_head;
			return *this;
		}
		
		Iterator const operator++ (int)
		{
			Iterator old = *this;
			++*this;
			return old;
		}

		Iterator& operator-- (void)
		{
			if (m_node)
				m_node = m_node->m_prev;
			else
				m_node = m_tail;
			return *this;
		}
		
		Iterator const operator-- (int)
		{
			Iterator old = *this;
			--*this;
			return old;
		}

		T& operator* (void) const
		{
			return m_node->m_data;
		}

		T* operator->(void) const
		{
			return &**this;
		}
	private:
		Node* m_head;
		Node* m_tail;
		Node* m_node;
		friend class List;
	};

	// 获取起始正向迭代器————指向第一个元素
	Iterator begin(void)
	{
		return Iterator(m_head, m_tail, m_head);
	}

	// 获取终止正向迭代器————指向最后一个元素的下一个位置
	Iterator end(void)
	{
		return Iterator(m_head, m_tail);
	}

	// 在正向迭代器前插入,返回指向新插入元素的迭代器
	Iterator insert(Iterator loc, T const& data)
	{
		if (loc == end())
		{
			push_back(data);
			return Iterator(m_head, m_tail, m_tail);
		}
		else
		{
			Node* node = new Node(data, loc.m_node->m_prev, loc.m_node);
			if (node->m_prev)
				node->m_prev->m_next = node;
			else
				m_head = node;
			node->m_next->m_prev = node;
			return Iterator(m_head, m_tail, node);
		}
	}

	// 删除迭代器所指向的元素,并返回该元素之后的迭代器
	Iterator erase(Iterator loc)
	{
		if (loc == end())
			throw invalid_argument("无效参数!");
		if (loc.m_node->m_prev)
			loc.m_node->m_prev->m_next = loc.m_node->m_next;
		else
			m_head = loc.m_node->m_next;
		if (loc.m_node->m_next)
			loc.m_node->m_next->m_prev = loc.m_node->m_prev;
		else
			m_tail = loc.m_node->m_prev;
		Node* next = loc.m_node->m_next;
		delete loc.m_node;
		return Iterator(m_head, m_tail, next);
	}

	// 常正向迭代器
	// 反向迭代器
	// 常反向迭代器

};

// 针对char const* 类型的成员特化版本
template<>
bool List<char const*>::equal(char const* const& a, char const* const& b) const
{
	return (0 == strcmp(a, b));
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

【C++】双向线性链表容器的实现

标签:c++   stl   list   容器   

原文地址:http://blog.csdn.net/qq_26369213/article/details/47324389

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!