最近在复习数据结构的内容,模仿了stl中的list、vector、queue和stack.当然是精简版的了,只写了最基本的功能。
这里要注意一点,模板类的类声明和定义要在同一个文件内,最好是在头文件内。因为模板类和模板函数在使用的时候才会被实例化,所以编译器需要知道所有的实现代码,然后去实例化各种数据类型的类或者函数。所以如果把类定义放在单独的源文件中的话,编译器找不到相关定义。
list
代码如下,这里实现的是双向循环链表
// list头文件
#pragma once
#include<exception>
template<typename T>
class list
{
public:
list();
virtual ~list();
list(const list<T>& ob);
list(list<T>&& ob);
list<T> & operator= (const list<T> & ob);
list<T> & operator= (list<T> && ob);
private:
unsigned int m_nLength;
node<T> * m_tailNode;
public:
// 获取元素值
T getElement(unsigned int index) const;
// 获取头节点值
T get_front() const;
// 获取尾节点值
T get_back() const;
// 插入元素
bool insert(unsigned int index, T elem);
// 插入首位
bool insert_front(T elem);
// 在尾部插入
bool insert_back(T elem);
// 设置某个位置的值
bool setValue(unsigned int index, T value);
// 删除某个节点并返回该节点的值
T deleteElement(unsigned int index);
// 删除头节点,返回该节点的值
T delete_front();
// 删除尾节点并返回该节点的值
T delete_back();
// 删除所有节点
void deleteAll();
// 获取链表长度
unsigned int getLength() const;
// 链表是否为空
bool empty() const;
};
template<typename T>
list<T>::list() : m_tailNode(nullptr), m_nLength(0u)
{
}
template<typename T>
list<T>::~list()
{
deleteAll();
m_tailNode = nullptr;
}
template<typename T>
list<T>::list(const list<T> & ob)
{
try
{
unsigned int n = 0;
while (n < ob.getLength())// 拷贝元素节点
{
insert_back(ob.getElement(n));
n++;
}
}
catch (std::exception e)
{
deleteAll();
e.what();
}
}
template<typename T>
list<T>::list(list<T> && ob)
{
m_tailNode = ob.m_tailNode;
m_nLength = ob.m_nLength;
ob.m_tailNode = nullptr;
ob.m_nLength = 0u;
}
template<typename T>
list<T> & list<T>::operator= (const list<T> & ob)
{
if (!empty())
{
deleteAll();
m_tailNode = nullptr;
}
try
{
unsigned int n = 0;
unsigned int nLength = ob.getLength();
while (n < nLength)
{
insert_back(ob.getElement(n));
n++;
}
}
catch (std::exception e)
{
deleteAll();
e.what();
}
return * this;
}
template<typename T>
list<T> & list<T>::operator= (list<T> && ob)
{
m_tailNode = ob.m_tailNode;
m_nLength = ob.m_nLength;
ob.m_tailNode = nullptr;
ob.m_nLength = 0u;
return * this;
}
template<typename T>
T list<T>::getElement(unsigned int index) const
{
if (index >= m_nLength)
{
std::cout << "out of ranges" << std::endl;
return 0;
}
T temp;
if (index <= m_nLength / 2)
{
unsigned int n = 0;
node<T> * pnode = m_tailNode;
while (n++ <= index)
{
pnode = pnode->next;
}
temp = pnode->data;
}
else
{
unsigned int n = m_nLength - 1;
node<T> * pnode = m_tailNode;
while (n-- > index)
{
pnode = pnode->pre;
}
temp = pnode->data;
}
return temp;
}
template<typename T>
T list<T>::get_front() const
{
return getElement(0u);
}
template<typename T>
T list<T>::get_back() const
{
if (m_nLength == 0u)
{
return T;
}
return get_Element(m_nLength - 1);
}
template<typename T>
bool list<T>::insert(unsigned int index, T elem)
{
if (index > m_nLength)
{
std::cout << "out of ranges" << std::endl;
return false;
}
if (0u == m_nLength)
{
node<T> * pnode = new node<T>;
if (nullptr == pnode)
{
throw (std::exception("内存分配出错!"));
}
m_tailNode = pnode;
pnode->data = elem;
pnode->next = m_tailNode;
pnode->pre = m_tailNode;
}
else if (0u == index)// 插入第一位置
{
node<T> * pnode = new node<T>;
pnode->data = elem;
pnode->next = m_tailNode->next;
m_tailNode->next = pnode;
pnode->pre = m_tailNode;
pnode->next->pre = pnode;
}
else if (m_nLength == index)// 插入尾部
{
node<T> * pnode = new node<T>;
pnode->data = elem;
pnode->next = m_tailNode->next;
m_tailNode->next = pnode;
pnode->pre = m_tailNode;
pnode->next->pre = pnode;
m_tailNode = pnode;
}
else if (index <= m_nLength / 2)
{
node<T> * pnode = m_tailNode;
unsigned int n = 0u;
while (n++ < index)// 定位到index上一个节点
{
pnode = pnode->next;
}
// 插入节点
node<T> * pnodeElem = new node<T>;
pnodeElem->data = elem;
pnodeElem->next = pnode->next;
pnode->next = pnodeElem;
pnodeElem->pre = pnode;
pnodeElem->next->pre = pnodeElem;
}
else
{
node<T> * pnode = m_tailNode;
unsigned int n = m_nLength - 1;
while (--n > index )// 定位到index上一个节点
{
pnode = pnode->pre;
}
node<T> * pnodeElem = new node<T>;
pnodeElem->data = elem;
pnodeElem->pre = pnode->pre;
pnode->pre = pnodeElem;
pnodeElem->next = pnode;
pnodeElem->pre->next = pnodeElem;
}
// 长度增加
m_nLength++;
return true;
}
template<typename T>
bool list<T>::insert_front(T elem)
{
return insert(0u, elem);
}
template<typename T>
bool list<T>::insert_back(T elem)
{
return insert(m_nLength, elem);
}
template<typename T>
bool list<T>::setValue(unsigned int index, T value)
{
if (index >= m_nLength)
{
std::cout << "out of ranges" << std::endl;