DualLinkList
双向链表的由来:单链表只可以向后访问,如果要逆序访问,效率将会很低
双向链表的特点:
比单链表多了前驱,可以逆序访问
提供游标与步长,使用方式与单链表相同
DualLinkList.h
#ifndef _DualLinkList_H_
#define _DualLinkList_H_
#include "include/LinuxList.h"
#include "include/Exception.h"
namespace JYlib
{
/* 双向链表
功能:
*/
template < typename T >
class DualLinkList:public List<T>
{
protected:
#pragma pack(4)
struct Node : public Object
{
T value;
Node* next;
Node* pre;
};
/*
不直接使用Node*声明(使用sizeof),是为了避开泛指类型T的构造,因为T的构造可能会发生异常
都继承自顶层父类,保证内存布局与node相同,就可以通过retinterpret_cast强制转换来使用
mutable的声明是因为const成员函数中会取m_header的地址
*/
mutable struct : public Object
{
char reserved[sizeof(T)];
Node* next;
Node* pre;
}m_header;
#pragma pack()
int m_length;
Node* m_current;//游标当前位置
int m_step;//游标步进的长度
//定位对象的前一个位置
Node* position(int i)const
{
Node* ret = reinterpret_cast<Node*>(&m_header);
for(int j = 0;j < i;j++)
{
ret = ret->next;
}
return ret;
}
//封装申请与删除 增强拓展性
virtual Node* create()
{
return new Node();
}
virtual void destroy(Node* pn)
{
delete pn;
}
public:
DualLinkList()
{
m_header.pre = NULL;
m_header.next = NULL;
m_current = NULL;
m_step = 1;
m_length = 0;
}
DualLinkList(const List<T>& t);
DualLinkList& operator =(const List<T>& e);
bool insert(const T& e)
{
return insert(m_length,e);
}
bool insert(int i,const T& e)
{
bool ret = (0 <= i)&&(i <= m_length);//小于等于是为了可以在末尾插入
if(ret)
{
Node* new_Node = create();
if(new_Node != NULL)
{
Node* current = position(i);
Node* next = current->next;
new_Node->value = e;
current->next = new_Node;
new_Node->next = next;
if(current != reinterpret_cast<Node*>(&m_header))//如果不是首结点
{
new_Node->pre = current;
}
else
{
new_Node->pre = NULL;
}
if(next != NULL)//下一个节点是否使用
{
next->pre = new_Node;
}
m_length++;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create DynamicList object ...");
}
}
return ret;
}
bool remove(int i)
{
bool ret = ((0 <= i)&&(i < m_length));
if(ret)
{
Node* current = position(i);
Node* remove = current->next;
Node* next = remove->next;
if(m_current == remove)//如果当前游标在此,则游标指向下一个位置
{
m_current = next;
}
current->next = next;
if(next != NULL)
{
if(current == reinterpret_cast<Node*>(&m_header))//如果是首结点,前一个节点为空
{
next->pre = NULL;
}
else
{
next->pre = current;
}
}
m_length--;
destroy(remove);//先改数据,后析构,即使析构出问题,其仍然已经不是单链表一员
}
return ret;
}
bool set(int i,const T& e)
{
bool ret = (0 <= i)&&(i < m_length);
if(ret)
{
position(i)->next->value = e;
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException,"Parameter i is invalid ...");//抛出数组越界异常
}
return ret;
}
bool get(int i,T& e)const
{
bool ret = (0 <= i)&&(i < m_length);
if(ret)
{
e = position(i)->next->value;
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException,"Parameter i is invalid ...");//抛出数组越界异常
}
return ret;
}
virtual T get(int i)const
{
T ret;
get(i,ret);
return ret;
}
int find(const T& e)const
{
int ret = -1;
int i = 0;
Node* node = m_header.next;
while(node != NULL)
{
if(node->value == e)
{
ret = i;
break;
}
else
{
node = node->next;
i++;
}
}
return ret;
}
int length(void)const
{
return m_length;
}
//游标移动到目的地址,并重设置步进值
virtual bool 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;
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException,"Parameter i is invalid ...");//抛出数组越界异常
}
return ret;
}
//游标是否到末尾
virtual bool end()
{
return (m_current == NULL);
}
//当前游标的值
virtual T current()
{
if(!end())
{
return m_current->value;
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException,"Parameter i is invalid ...");//抛出数组越界异常
}
}
//步进至一个游标
virtual bool next()
{
int i = 0;
while((i < m_step)&&(!end()))
{
m_current = m_current->next;
i++;
}
return (i == m_step);
}
virtual bool pre()
{
int i = 0;
while((i < m_step)&&!end())
{
m_current = m_current->pre;
i++;
}
return (i == m_step);
}
void clear()
{
while(m_length > 0)
{
remove(0);
}
}
~DualLinkList()
{
clear();
}
};
}
#endif
DualCircleList
通过Linux内核链表实现:
DualCircleList_Linux.h
#ifndef _DualCircleLinkList_Linux_H_
#define _DualCircleLinkList_Linux_H_
#include "include/DualLinkList.h"
#include "include/LinuxList.h"
namespace JYlib
{
/* 双向循环链表
功能:增删查改 前序与后序遍历
*/
template < typename T>
class DualCircleList_Linux:public DualLinkList<T>
{
protected:
struct Node:public Object
{
list_head head;//双指针结构体
T value;
};
list_head m_header;
list_head* m_current;
list_head* position(int i)const
{
list_head* ret = const_cast<list_head*>(&m_header);
for(int p=0;p<i;p++)
{
ret = ret->next;
}
return ret;
}
int mod(int i)const
{
return (this->m_length == 0 ? 0 : i%(this->m_length));
}
public:
DualCircleList_Linux():DualLinkList<T>()
{
m_current = NULL;
INIT_LIST_HEAD(&m_header);
}
bool insert(const T& e)
{
return insert(this->m_length,e);
}
bool insert(int i,const T& e)
{
bool ret = true;
i = i % (this->m_length + 1);
Node* new_node = new Node();
if(new_node != NULL)
{
new_node->value = e;
list_add_tail(&new_node->head,position(i)->next);
this->m_length++;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException,"No memory to insert new element ...");
}
return ret;
}
bool remove(int i)
{
i = mod(i);
bool ret =(0 <= i)&&(i < this->m_length);
if(ret)
{
list_head* remove = position(i)->next;
if(m_current == remove)
{
m_current = m_current->next;
}
list_del(remove);
this->m_length--;
delete list_entry(remove,Node,head);
}
return ret;
}
T get(int i)const
{
T ret;
get(i,ret);
return ret;
}
bool get(int i,T& e)const
{
i = mod(i);
bool ret = ( (0 <= i)&&(i < this->m_length) );
if(ret)
{
e = list_entry(position(i)->next,Node,head)->value;
}
return ret;
}
bool set(int i,const T& e)
{
i = mod(i);
bool ret = ( (0 <= i)&&(i < this->m_length) );
if(ret)
{
list_entry(position(i)->next,Node,head)->value = e;
}
return ret;
}
int find(const T& e)const
{
int ret = -1;
int i = 0;
list_head* silder = NULL;
list_for_each(silder,&m_header)
{
if(list_entry(silder,Node,head)->value == e)
{
ret = i;
break;
}
i++;
}
return ret;
}
bool move(int i,int step = 1)
{
bool ret = (step > 0);
i = mod(i);
ret = ret && (0 <= i) && (i < this->m_length);
if(ret)
{
m_current = position(i)->next;
this->m_step = step;
}
return ret;
}
bool end()
{
return (m_current == NULL || this->m_length == 0);
}
//当前游标的值
T current()
{
if(!end())
{
return list_entry(m_current,Node,head)->value;
}
else
{
THROW_EXCEPTION(IndexOutOfBoundsException,"Parameter i is invalid ...");//抛出数组越界异常
}
}
//步进至一个游标
bool next()
{
int i = 0;
while((i < this->m_step)&&!end())
{
if(m_current != &m_header)
{
m_current = m_current->next;
i++;
}
else
{
m_current = m_current->next;
}
}
if(m_current == &m_header)
{
m_current = m_current->next;
i++;
}
return (i == this->m_step);
}
bool pre()
{
int i = 0;
while((i < this->m_step)&&!end())
{
if(m_current != &m_header)
{
m_current = m_current->prev;
i++;
}
else
{
m_current = m_current->prev;
}
}
if(m_current == &m_header)
{
m_current = m_current->prev;
i++;
}
return (i == this->m_step);
}
void clear()
{
while(this->m_length > 0)
{
remove(0);
}
}
~DualCircleList_Linux()
{
clear();
}
};
}
#endif
通过双向链表以及循环链表实现:
DualCircleList.h
#ifndef _DualCircleLinkList_H_
#define _DualCircleLinkList_H_
#include "include/DualLinkList.h"
namespace JYlib
{
template < typename T>
class DualCircleList:public DualLinkList<T>
{
protected:
typedef typename DualCircleList<T>::Node Node;
int mod(int i)const
{
return (this->m_length == 0 ? 0 : i%(this->m_length));
}
Node* last()
{
return (this->position(this->m_length));
}
void last_to_first()
{
Node* m_last = last();
this->m_header.next->pre = m_last;
m_last->next = this->m_header.next;
}
public:
DualCircleList():DualLinkList<T>()
{
}
bool insert(const T& e)
{
return insert(this->m_length,e);
}
bool insert(int i,const T& e)
{
bool ret = DualLinkList<T>::insert(i,e);
i = i % (this->m_length + 1);
if(ret && (i == 0))
{
last_to_first();
}
return ret;
}
bool remove(int i)
{
bool ret = false;
i = mod(i);
if(i == 0)//删除的是头结点
{
Node* remove = this->m_header.next;
Node* next = remove->next;
if(remove == NULL)
{
return false;
}
else
{
this->m_length--;
this->m_header.next = next;
if(next == NULL)//除首结点外无节点
{
this->m_header.next = NULL;
this->m_header.pre = NULL;
this->m_current = NULL;
}
else//除首结点外有节点
{
if(this->m_current == remove)
{
this->m_current = this->m_current->next;
}
last_to_first();
}
this->destroy(remove);
ret = true;
}
}
else//删除非头结点
{
ret = DualLinkList<T>::remove(i);
}
return ret;
}
T get(int i)const
{
return DualLinkList<T>::get(mod(i));
}
bool get(int i,const T& e)const
{
return DualLinkList<T>::get(mod(i),e);
}
bool set(int i,const T& e)
{
return DualLinkList<T>::set(mod(i),e);
}
int find(const T& e)const
{
int ret = -1;
Node* silder = this->m_header.next;
for(int i=0;i<this->m_length;i++)
{
if(silder->value == e)
{
ret = i;
break;
}
silder = silder->next;
}
return ret;
}
void clear()
{
if(this->m_length > 0)
{
while(this->m_length > 1)
{
remove(1);
}
if(this->m_length == 1)
{
Node* remove = this->m_header.next;
this->m_header.next = NULL;
this->m_header.pre = NULL;
this->m_current = NULL;
this->m_length = 0;
this->destroy(remove);
}
}
}
bool move(int i,int step = 1)
{
return DualLinkList<T>::move(mod(i),step);
}
bool end()
{
return (this->m_length == 0)||(this->m_current == NULL);
}
~DualCircleList()
{
clear();
}
};
}
#endif