在顺序表(c++实现)一文中讲到,顺序表是基于顺序存储结构的数据结构,即用一段地址连续的存储单元依次存储数据元素,与之相对的另一种线性表–链表,它则是基于链式存储结构的数据结构:数据元素除了存储本身的信息之外,还需要存储器直接后继(和前驱)的信息,前者是数据域,后者是指针域。
线性表共有的操作,封装在List类中:
//List.h
#ifndef __LIST_H__
#define __LIST_H__
#include <exception>
#include <stdio.h>
template<typename T>
class List
{
public:
List() {}
virtual bool insert(const T& e) = 0;
virtual bool insert(int i, const T& e) = 0;
virtual bool remove(int i) = 0;
virtual bool set(int i, const T& e) = 0;
virtual bool get(int i, T& e) const = 0;
virtual int find(const T& e) const = 0;
virtual int length() const = 0;
virtual void clear() = 0;
protected:
List(const List& );
List& operator=(const List& );
};
#endif /* __LIST_H__ */
链表类LinkList是List的派生类,实现List中的纯虚函数:
//LinkList.h
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include "List.h"
#include <iostream>
//LinkList类用于维护链表
template<typename T>
class LinkList : public List<T>
{
protected:
struct Node_t //链表中数据成员的类型定义
{
T value;
Node_t* next;
};
mutable struct { //定义头节点,方便链表操作。其内存布局和Node_t一致
char reserved[sizeof(T)];
Node_t* next;
}m_header;
int m_length;
int m_step; //链表移动操作的步长
Node_t* m_current; //当前指向的链表节点,相当于游标、迭代器
Node_t* position(int i) const //返回目标节点的位置
{
Node_t *ret = reinterpret_cast<Node_t*>(&m_header);
for (int p = 0; p < i; ++p)
ret = ret->next;
return ret;
}
virtual Node_t* CreateNode()
{
return new Node_t;
}
virtual void DestoryNode(Node_t* pn)
{
delete pn;
}
public:
LinkList()
{
m_header.next = NULL;
m_length = 0;
m_step = 1;
m_current = NULL;
}
bool insert(int i, const T& e) //插入
{
bool ret = ((i >= 0) && (i <= m_length));
if (ret)
{
Node_t *node = CreateNode();
if (node)
{
//定位到目标位置
Node_t* cur = position(i);
node->value = e;
node->next = cur->next;
cur->next = node;
//cur->
++m_length;
}
}
else
throw(std::out_of_range("LinkList::insert(): i of randge"));
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_t* cur = position(i);
Node_t* del = cur->next;
cur->next = del->next;
--m_length;
DestoryNode(del);
}
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)) return ret;
else throw(std::out_of_range("LinkList::get(int i): i of randge"));
}
int find(const T& e) const
{
int ret = -1;
int i = 0;
Node_t* 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_t* del = m_header.next;
m_header.next = del->next;
--m_length;
DestoryNode(del);
}
}
//将m_current移动到目标位置,step参数用于设置移动步长
int move(int i, int step = 1)
{
bool ret = ((0 <= i) && (i < m_length) && (step > 0));
if (ret)
{
m_current = position(i)->next;
m_step = step; //??
}
return ret;
}
bool end()
{
return (m_current == NULL);
}
T current()
{
if (!end()) return m_current->value;
else throw(std::out_of_range("LinkList::current()"));
}
//将m_current指向下一个步长的位置
bool next()
{
int i = 0;
while ((i < m_step) && !end())
{
m_current = m_current->next;
++i;
}
return i == m_step;
}
~LinkList()
{
printf("~LinkList()\n");
clear();
}
};
#endif /* __LINKLIST_H__ */
使用:
//main.cpp
#include <iostream>
#include "LinkList.h"
#include "StaticLinkList.h"
using namespace std;
int main(void)
{
LinkList<int> ll;
for (int i = 0; i < 6; ++i)
{
ll.insert(0, i);
}
//通过游标LinkList<int>::m_current来遍历链表的数据成员
for (ll.move(0); !ll.end(); ll.next())
cout << ll.current() << endl;
getchar();
return 0;
}
运行: