用模板技术实现链表可适用不同类型的数据类型
单链表:每个结点只包含该结点存储的数据以及直接后继的地址信息
头结点:头结点不存储数据但是存储下一个结点的地址,只是用来方便遍历链表
这里的头结点,需要单独来处理,因为当泛指类型为类类型时,若由于研发人员定义的类有问题,然后存储在链表里,那么抛异常就会抛到链表类这里来了,所以头结点的value用占位数组char reserved[sizeof(T)]来实现,而非直接定义一个泛指类型T value。在内存排布上需要跟普通结点一样。
插入结点:
删除结点:
#ifndef __LINKLIST_H
#define __LINKLIST_H
template <typename T>
class LinkList
{
private:
struct Node
{
T value;
Node* next;
};
//若T为类类型,若创建对象时,泛指类型抛出了异常,就会出问题,为了程序的健壮性,头节点单独定义,定义一个同样大小空间的数组占位,这样可避免这种情况发生。
mutable struct
{
char reserved[sizeof(T)];
Node* next;
}m_header;
int m_length;
//返回i位置对应的节点,因为操作会经常用到,单独做成一个函数调用会更简洁
Node* position(int i) const
{
Node* ret = reinterpret_cast<Node*>(&m_header);
for(int p=0; p<i; p++)
{
ret = ret->next;
}
return ret;
}
public:
LinkList()
{
m_header.next = NULL;
m_length = 0;
}
bool insert(int i, const T& e)
{
bool ret = (0 <= i) && (i <= m_length);
if(ret)
{
Node* node = new Node();
if(node)
{
Node* current = position(i);
node->value = e;
node->next = current->next;
current->next = node;
m_length++;
}
else
{
cout << "No memory to insert new element..." << endl;
}
}
return ret;
}
//在尾部插入
bool insert(const T& e)
{
return insert(m_length, e);
}
bool remove(int i)
{
bool ret = (0 <= i) && (i < m_length);
if(ret)
{
Node* toDel = position(i)->next;
position(i)->next = toDel->next;
m_length--;
delete toDel;
}
return ret;
}
bool set(int i, const T& e)
{
bool ret = (0 <= i) && (i < m_length);
if(ret)
{
position(i)->next->value = e;
}
return ret;
}
bool get(int i, T& e) const
{
bool ret = (0 <= i) && (i < m_length);
if(ret)
{
e = position(i)->next->value;
}
return ret;
}
T get(int i) const
{
T ret;
if( !get(i, ret) )
{
cout << "Invalid Parameter i to get element..." << endl;
}
return ret;
}
int find(const T& e) const
{
int ret = -1;
int i = 0;
Node* node = m_header.next;
while(node)
{
if(node->value == e)
{
ret = i;
break;
}
else
{
node = node->next;
i++;
}
}
return ret;
}
int length() const
{
return m_length;
}
void clear()
{
while(m_header.next)
{
Node* toDel = m_header.next;
m_header.next = toDel->next;
m_length--;
delete toDel;
}
}
~LinkList()
{
clear();
}
};
#endif
#include<iostream>
#include "LinkList.h"
using namespace std;
int main()
{
LinkList<int> list;
for(int i = 0; i < 5; i++)
{
list.insert(0, i);
list.set(0, i*i);
}
for(int i = 0; i < list.length(); i++)
{
cout << list.get(i) << " ";
}
cout << endl;
list.remove(2);
for(int i = 0; i < list.length(); i++)
{
cout << list.get(i) << " ";
}
list.clear();
for(int i = 0; i < list.length(); i++)
{
cout << list.get(i) << " ";
}
return 0;
}