线性表的链式存储结构(链表)
链表:基于来链式存储的线性表
链式逻辑存储结构:基于链式存储结构的线性表中,每个节点都包含数据域和指针域(数据域:存储数据元素本身。指针域:存储相邻节点的地址。)
单链表:链表的每个节点只包含后一个元素的地址信息
循环链表:链表的最后一个元素的包含第一个元素的地址信息
双向链表:链表的节点中包含后驱和前驱的地址信息
链表基本概念: 头节点(辅助节点。不包含数据域,指针域指向第0个数据元素)+ 数据节点(数据域+地址域)+ 尾节点(指针域为空或某一值,只有数据域)
单链表节点定义:
struct node: public TopClass // { T value; // Node* next; // }
单链表的表现形式:
单链表操作:插入操作
单链表的继承关系:
LinkList.h
/* * LinkList: 链表类 * 成员变量: * Node 节点 * m_handler 头部辅助节点 * m_length 节点数 * 成员函数: * create() * destroy() * * LinkList() 构造函数初始成员变量 * insert() 参数判断,申请新节点,寻找节点,插入节点 * remove() 参数判断,寻找节点,删除节点 * set() 参数判断,寻找节点,设置节点值 * get() 参数判断,寻找节点,获取节点值 * length() 获取链表长度 * clean() 释放所有节点空间 * ~LinkList() 释放所有节点空间 * * move() 移动游标到指定位置 * end() 判断游标是否到最后 * current() 回去当前游标节点值 * next() 移动步长的节点数 */ #ifndef LINKLIST_H #define LINKLIST_H #include"List.h" #include"Exception.h" namespace DSL { template <typename T> class LinkList : public List<T> { protected: struct Node : public TopClass { T value; Node* next; }; //mutable Node m_handler; // 头节点中包含了数据域,当泛指类型中构造函数抛出异常时,此处会调用构造函数发生异常 mutable struct : public TopClass // 继承顶层父类使得内存布局相同 { char reserved[sizeof(T)]; Node* next; }m_handler; int m_length; // 链表长度 int m_step; // 游标每次移动数目 Node* m_current; // 游标位置 virtual Node* create(const T& value) { Node* node = new Node(); node->value = value; return node; } virtual void destroy(Node* node) { delete node; } public: LinkList() { m_handler.next = NULL; m_length = 0; m_step = 1; m_current = NULL; } bool insert(const T& obj) { return insert(m_length,obj); } bool insert(int pos, const T& obj) { bool ret = ((pos >= 0) && (pos <= m_length)); if(ret) { Node* node =create(obj); if(node != NULL) { Node* current = reinterpret_cast<Node*>(&m_handler); for(int i = 0; i < pos; i++) { current = current->next; } node->next = current->next; current->next = node; m_length++; } else { THROW_EXCEPTION(NotEnoughMemoryException,"error: no enough memory to create node!"); } } return ret; } bool remove(int pos) { bool ret = ((pos >= 0) && (pos < m_length)); if(ret) { Node* current = reinterpret_cast<Node*>(&m_handler); for(int i = 0; i < pos; i++) { current = current->next; } Node* toDel = current->next; current->next = toDel->next; destroy(toDel); m_length--; } else { THROW_EXCEPTION(IdexOutOfBoundException,"error: index out of bound!"); } return ret; } bool set(int pos,const T& obj) { bool ret = ((0 <= pos) && (pos < m_length)); if(ret) { Node* current = reinterpret_cast<Node*>(&m_handler); for(int i = 0; i < pos; i++) { current = current->next; } current->next->value = obj; } else { THROW_EXCEPTION(IdexOutOfBoundException,"error: index out of bound!"); } return ret; } T get(int pos) const { T ret; get(pos, ret); return ret; } bool get(int pos, T& obj) const { bool ret = ((0 <= pos) && (pos < m_length)); if(ret) { Node* current = reinterpret_cast<Node*>(&m_handler); //const成员函数不可以修改成员变量的值 for(int i = 0; i < pos; i++) { current = current->next; } obj = current->next->value; } else { THROW_EXCEPTION(IdexOutOfBoundException,"error: index out of bound!"); } return ret; } int find(const T& obj) const { int ret = -1; Node* current = reinterpret_cast<Node*>(&m_handler); current = current->next; for(int i = 0; i <= m_length; i++) { if( current->value == obj) // 当泛指类型为对象时,无法比较,要在TopClass中重载==操作符 { ret = i; break; } else { current = current->next; } } return ret; } int length() const { return m_length; } void clean() { while(m_handler.next) { Node* toDel = m_handler.next; m_handler.next = toDel->next; delete toDel; } m_length = 0; } bool move(int addr) // 移动到addr节点 { bool ret = ((0 <= addr) && (addr < m_length)); if(ret) { Node* current = reinterpret_cast<Node*>(&m_handler); for(int i = 0; i < addr; i++) { current = current->next; } m_current = current->next; } return ret; } bool end() // 判断游标是否在链表尾部 { return (m_current == NULL); } T current() //返回游标所在节点的值 { if(!end()) { return m_current->value; } else { THROW_EXCEPTION(InvalidOperationException,"error: operation a no exit node!"); } } bool next(int step = 1) // 一次移动步长为m_step的节点 { bool ret = ((0 < step) && (step <= m_length)); if(ret) { int i = 0; while((i < step) && (!end())) { m_current = m_current->next; i++; } return (i == step); } else { THROW_EXCEPTION(InvalidOperationException,"error: operation node over max node number!"); } } ~LinkList() { clean(); } }; } #endif
顺序表:访问需求较大的场合
单链表:数据频繁插入的场合
静态单链表:StaticLinkList
数据最大元素固定且需要频繁的增删元素时采用静态单链表。
实现原理:分配一个固定大小内存空间( m_pool[] ),所有节点从这里申请和归还(create()和destroy()),指定空间创建对象(重载new)。
StaticLinkList.h
/* * StaticLinkList:静态单链表 * 成员变量: * Snode: 重载new的Node节点 * m_pool[]: 固定大小内存池 * m_flag[]: 标记使用了的节点 * 成员函数: * create() 内存池中申请节点空间 * destroy() 返回节点空间到内存池 * * StaticLinkList() 初始化标记 * capacity() 获取内存池大小 * */ #ifndef STATICLINKLIST_H #define STATICLINKLIST_H #include"LinkList.h" namespace DSL { template < typename T, int N > class StaticLinkList : public LinkList<T> { protected: typedef typename LinkList<T>::Node Node; struct Snode : public Node { void* operator new (size_t size, void* addr) { return addr; } }; unsigned char m_pool[sizeof(Node) * N]; char m_flag[N]; Node* create() { Snode* addr = NULL; for(int i = 0; i < N; i++) { if(m_flag[i] == 0) { addr = reinterpret_cast<Snode*>(m_pool + i*sizeof(Snode)); addr = new(addr) Snode(); // 从m_pool中申请节点空间,并调用构造函数 m_flag[i] = 1; break; } } return addr; } void destroy(Node* addr) { Snode* toDel = dynamic_cast<Snode*>(addr); for(int i = 0; i < N; i++) { if(toDel == reinterpret_cast<Snode*>(&m_pool[i*sizeof(Node)])) { m_flag[i] == 0; toDel->~Node(); break; } } } public: StaticLinkList() { for(int i = 0; i < N; i++) { m_flag[i] = 0; } } int capacity() { return N; } ~StaticLinkList() // 默认析构函数调用父类LinkList的析构函数,会直接释放内存池的空间 { this->clean(); // 调用父类的clean函数,会调用子类的destroy函数。 } // 构造,析构函数调用的虚函数是调用当前类的实现的版本 }; } #endif