SmartOS/List.h

772 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _List_H_
#define _List_H_
#include <stddef.h>
#include "Sys.h"
// 数组长度
#define ArrayLength(arr) sizeof(arr)/sizeof(arr[0])
// 数组清零,固定长度
#define ArrayZero(arr) memset(arr, 0, ArrayLength(arr) * sizeof(arr[0]))
// 数组清零,可变长度
#define ArrayZero2(arr, len) memset(arr, 0, len * sizeof(arr[0]))
// 数组复制
#define ArrayCopy(dst, src) memcpy(dst, src, ArrayLength(src) * sizeof(src[0]))
// 数组长度
//#define ArrayLength(arr) sizeof(arr)/sizeof(arr[0])
// 从数组创建列表
#define MakeList(T, arr) List<T>(&arr[0], sizeof(arr)/sizeof(arr[0]))
// 迭代器
template<typename T>
class IEnumerator
{
public:
virtual T& Current() = 0; // 获取集合中的当前元素
virtual bool MoveNext() = 0; // 将枚举数推进到集合的下一个元素
virtual void Reset() = 0; // 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前
virtual void Remove() = 0; // 从列表中移除当前节点
};
// 公开枚举数,该枚举数支持在指定类型的集合上进行简单迭代
template<typename T>
class IEnumerable
{
public:
virtual IEnumerator<T>* GetEnumerator() = 0; // 返回一个循环访问集合的枚举数
};
// 集合接口
template<typename T>
class ICollection
{
public:
virtual int Count() const = 0; // 集合中包含的元素数
virtual void Add(const T& item) = 0; // 将某项添加到集合
virtual void Remove(const T& item) = 0; // 从集合中移除特定对象的第一个匹配项
virtual bool Contains(const T& item)= 0; // 确定集合是否包含特定值
virtual void Clear() = 0; // 从集合中移除所有项
virtual void CopyTo(T* arr) = 0; // 将集合元素复制到数组中
};
// foreach宏用于遍历迭代器接口必须和foreach_end成对出现
#define foreach(cls,cur,list) \
{ \
IEnumerator<cls>* et = list.GetEnumerator();\
while(et->MoveNext()) \
{ \
cls cur = et->Current(); \
#define foreach_end() \
} \
delete et; \
}
// 用于在迭代器中删除当前节点的宏
#define foreach_remove() et->Remove();
// 数组
class Array
{
private:
void** _Arr;
int _Count;
int _Capacity;
public:
// 有效元素个数
int Count() const { return _Count; }
// 最大元素个数
int Capacity() const { return _Capacity; }
Array(int capacity = 0x10)
{
_Capacity = capacity;
_Count = 0;
_Arr = new void*[capacity];
ArrayZero2(_Arr, capacity);
}
~Array()
{
if(_Arr) delete _Arr;
_Arr = NULL;
}
// 压入一个元素
int Push(void* item)
{
assert_param(_Count < _Capacity);
// 找到空闲位放置
int idx = _Count++;
_Arr[idx] = item;
return idx;
}
// 弹出一个元素
const void* Pop()
{
assert_param(_Count > 0);
return _Arr[--_Count];
}
// 重载索引运算符[],让它可以像数组一样使用下标索引。
void* operator[](int i)
{
assert_param(i >= 0 && i < _Count);
return _Arr[i];
}
// 列表转为指针,注意安全
//T* operator=(Array arr) { return arr.Arr; }
};
// 固定大小的指针数组。
/*
用于数据元素不多,有个上限的场合。主要为了方便遍历。
存储数据时,从头开始找到空位来存放,不用时清空相应空位。
所以需要注意的是,在数组里面存储的元素不一定连续。
*/
template<typename T, int ArraySize>
class FixedArray
{
private:
uint _Count;
T* Arr[ArraySize];
public:
FixedArray()
{
_Count = 0;
ArrayZero(Arr);
}
FixedArray(FixedArray& arr)
{
_Count = arr._Count;
ArrayCopy(Arr, arr.Arr);
}
FixedArray& operator=(FixedArray& arr)
{
_Count = arr._Count;
ArrayCopy(Arr, arr.Arr);
return *this;
}
uint Count() const { return _Count; }
// 压入一个元素。返回元素所存储的索引
int Add(T* item)
{
assert_ptr(item);
//assert_param(_Count < ArraySize);
if(_Count >= ArraySize) return -1;
// 找到空闲位放置
int i = 0;
for(; i < ArraySize && Arr[i]; i++);
// 检查是否还有空位
if(i >= ArraySize) return -1;
Arr[i] = item;
_Count++;
return i;
}
// 弹出最后一个元素
T* Pop()
{
if(_Count == 0) return NULL;
// 找到最后一个元素
int i = ArraySize - 1;
for(; i >=0 && !Arr[i]; i--);
T* item = Arr[i];
_Count--;
Arr[i] = NULL;
return item;
}
// 删除元素
bool Remove(T* item)
{
int idx = Find(item);
if(idx < 0) return false;
RemoveAt(idx);
return true;
}
// 删除指定位置的元素
void RemoveAt(int idx)
{
assert_param(idx >= 0 && idx < ArraySize);
_Count--;
Arr[idx] = NULL;
}
FixedArray& Clear()
{
_Count = 0;
ArrayZero(Arr);
return *this;
}
// 释放所有指针指向的内存
FixedArray& DeleteAll()
{
for(int i=0; i < ArraySize; i++)
{
if(Arr[i]) delete Arr[i];
}
return *this;
}
// 查找元素
int Find(T* item)
{
assert_ptr(item);
int i = 0;
for(; i < ArraySize && Arr[i] != item; i++);
if(i >= ArraySize) return -1;
return i;
}
// 移到下一个元素累加参数如果没有下一个元素则返回false。
bool MoveNext(int& idx)
{
//assert_ptr(idx);
// 从idx开始找到第一个非空节点。注意存储不一定连续
int i = idx + 1;
for(; i < ArraySize && !Arr[i]; i++);
if(i >= ArraySize) return false;
idx = i;
return true;
}
// 重载索引运算符[],让它可以像数组一样使用下标索引。
/*T*& operator[](int i)
{
assert_param(i >= 0 && i < ArraySize);
return Arr[i];
}*/
// 不能允许[]作为左值否则外部直接设置数据以后Count并没有改变
T* operator[](int i)
{
assert_param(i >= 0 && i < ArraySize);
return Arr[i];
}
};
// 变长列表模版
template<typename T>
class List : public IEnumerable<T>, public ICollection<T>
{
private:
T* _Arr; // 存储数据的数组
uint _Count;// 拥有实际元素个数
uint _total;// 可容纳元素总数
void ChangeSize(int newSize)
{
if(_total == newSize) return;
T* arr2 = new T[newSize];
if(_Arr)
{
// 如果新数组较小,则直接复制;如果新数组较大,则先复制,再清空余下部分
if(newSize < _Count)
{
// 此时有数据丢失
memcpy(arr2, _Arr, newSize * sizeof(T));
_Count = newSize;
}
else
{
memcpy(arr2, _Arr, _Count * sizeof(T));
memset(&arr2[_Count], 0, (newSize - _Count) * sizeof(T));
}
delete[] _Arr;
}
else
ArrayZero2(arr2, newSize);
_Arr = arr2;
_total = newSize;
}
void CheckSize()
{
// 如果数组空间已用完,则两倍扩容
if(_Count >= _total) ChangeSize(_Count > 0 ? _Count * 2 : 4);
}
public:
List(int size = 0)
{
_Count = 0;
_total = size;
_Arr = NULL;
if(size)
{
_Arr = new T[size];
ArrayZero2(_Arr, size);
}
}
List(T* items, uint count)
{
_Arr = new T[count];
_Count = 0;
_total = count;
for(int i=0; i<count; i++)
{
_Arr[_Count++] = *items++;
}
}
~List() { if(_Arr) delete[] _Arr; _Arr = NULL; }
// 添加单个元素
virtual void Add(const T& item)
{
// 检查大小
CheckSize();
_Arr[_Count++] = item;
}
// 添加多个元素
void Add(T* items, int count)
{
int size = _Count + count;
if(size >= _total) ChangeSize(_Count > 0 ? _Count * 2 : 4);
for(int i=0; i<count; i++)
{
_Arr[_Count++] = *items++;
}
}
// 查找元素
int Find(const T& item)
{
for(int i=0; i<_Count; i++)
{
if(_Arr[i] == item) return i;
}
return -1;
}
virtual bool Contains(const T& item)
{
return Find(item) > -1;
}
// 删除指定位置元素
void RemoveAt(int index)
{
if(_Count <= 0 || index >= _Count) return;
// 复制元素
if(index < _Count - 1) memcpy(&_Arr[index], &_Arr[index + 1], (_Count - index - 1) * sizeof(T));
_Count--;
}
// 删除指定元素
virtual void Remove(const T& item)
{
int index = Find(item);
if(index >= 0) RemoveAt(index);
}
virtual void Clear()
{
_Count = 0;
}
virtual void CopyTo(T* arr)
{
assert_ptr(arr);
if(!_Count) return;
memcpy(arr, _Arr, _Count * sizeof(T));
}
// 返回内部指针
const T* ToArray() { return _Arr; }
// 有效元素个数
virtual int Count() const { return _Count; }
// 设置新的容量,如果容量比元素个数小,则会丢失数据
void SetCapacity(int capacity) { ChangeSize(capacity); }
// 重载索引运算符[],让它可以像数组一样使用下标索引。
T operator[](int i)
{
assert_param(i >= 0 && i < _Count);
return _Arr[i];
}
// 列表转为指针,注意安全
T* operator=(List& list) { return list.ToArray(); }
private:
class ListEnumerator : public IEnumerator<T>
{
private:
List* _List;
int _Index;
public:
ListEnumerator(List* list)
{
_List = list;
_Index = -1;
}
// 获取集合中的当前元素
virtual T& Current() { return _List->_Arr[_Index]; }
// 将枚举数推进到集合的下一个元素
virtual bool MoveNext()
{
_Index++;
if(_Index >= _List->_Count) _Index = -1;
return _Index >= 0;
}
// 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前
virtual void Reset() { _Index = -1; }
// 从列表中移除当前节点
virtual void Remove()
{
// 删除当前节点后,索引后移一位,因为后面的数据前移了一位
_List->RemoveAt(_Index);
_Index--;
}
};
public:
// 返回一个循环访问集合的枚举数。外部释放
virtual IEnumerator<T>* GetEnumerator()
{
return new ListEnumerator(this);
}
};
// 双向链表
template <class T> class LinkedList;
// 双向链表节点。实体类继承该类
template <class T> class LinkedNode
{
// 友元类。允许链表类控制本类私有成员
friend class LinkedList<T>;
public:
T* Prev; // 上一个节点
T* Next; // 下一个节点
void Initialize()
{
Next = NULL;
Prev = NULL;
}
// 从链表中删除。需要修改前后节点的指针指向,但当前节点仍然指向之前的前后节点
void RemoveFromList()
{
if(Prev) Prev->Next = Next;
if(Next) Next->Prev = Prev;
}
// 完全脱离链表。不再指向其它节点
void Unlink()
{
if(Prev) Prev->Next = Next;
if(Next) Next->Prev = Prev;
Next = NULL;
Prev = NULL;
}
// 把当前节点附加到另一个节点之后
void LinkAfter(T* node)
{
node->Next = (T*)this;
Prev = node;
// 不能清空Next因为可能是两个链表的合并
//Next = NULL;
}
// 最后一个节点
T* Last()
{
T* node = (T*)this;
while(node->Next) node = node->Next;
return node;
}
// 附加到当前节点后面
void Append(T* node)
{
Next = node;
node->Prev = (T*)this;
//node->Next = NULL;
}
};
// 双向链表
template <class T>
class LinkedList : public IEnumerable<T>, public ICollection<T>
{
public:
// 链表节点。实体类不需要继承该内部类
class Node
{
public:
T Item; // 元素
Node* Prev; // 前一节点
Node* Next; // 下一节点
Node()
{
Prev = NULL;
Next = NULL;
}
// 从队列中脱离
void RemoveFromList()
{
// 双保险,只有在前后节点指向当前节点时,才修改它们的值
if(Prev && Prev->Next == this) Prev->Next = Next;
if(Next && Next->Prev == this) Next->Prev = Prev;
}
// 附加到当前节点后面
void Append(Node* node)
{
Next = node;
node->Prev = this;
}
};
private:
Node* _Head; // 链表头部
Node* _Tail; // 链表尾部
int _Count; // 元素个数
void Init()
{
_Head = NULL;
_Tail = NULL;
_Count = 0;
}
void Remove(Node* node)
{
// 脱离队列
node->RemoveFromList();
// 特殊处理头尾
if(node == _Head) _Head = node->Next;
if(node == _Tail) _Tail = node->Prev;
delete node;
_Count--;
}
public:
LinkedList()
{
Init();
}
// 计算链表节点数
virtual int Count() const { return _Count; }
// 将某项添加到集合
virtual void Add(const T& item)
{
Node* node = new Node();
node->Item = item;
if(_Tail)
_Tail->Append(node);
else
_Head = _Tail = node;
_Count++;
}
// 从集合中移除特定对象的第一个匹配项
virtual void Remove(const T& item)
{
if(!_Count) return;
Node* node;
for(node = _Head; node; node = node->Next)
{
if(node->Item == item) break;
}
if(node) Remove(node);
}
// 确定集合是否包含特定值
virtual bool Contains(const T& item)
{
if(!_Count) return false;
Node* node;
for(node = _Head; node; node = node->Next)
{
if(node->Item == item) return true;
}
return false;
}
// 从集合中移除所有项。注意,该方法不会释放元素指针
virtual void Clear()
{
if(!_Count) return;
Node* node;
for(node = _Head; node;)
{
// 先备份,待会删除可能影响指针
Node* next = node->Next;
delete node;
node = next;
}
Init();
}
// 将集合元素复制到数组中
virtual void CopyTo(T* arr)
{
assert_ptr(arr);
if(!_Count) return;
Node* node;
for(node = _Head; node; node = node->Next)
{
*arr++ = node->Item;
}
}
private:
// 链表迭代器
class LinkedListEnumerator : public IEnumerator<T>
{
private:
LinkedList* _List;
Node* _Current; // 当前节点
Node* _Next; // 下一个节点。考虑到中途可能删节点,必须提前备好下一个
public:
LinkedListEnumerator(LinkedList* list)
{
_List = list;
_Current = NULL;
_Next = _List->_Head;
}
// 获取集合中的当前元素
virtual T& Current() { return _Current->Item; }
// 将枚举数推进到集合的下一个元素
virtual bool MoveNext()
{
// 总是提前计算下一个节点,以免中途当前节点被删除
_Current = _Next;
if(_Current) _Next = _Current->Next;
return _Current != NULL;
}
// 将枚举数设置为其初始位置,该位置位于集合中第一个元素之前
virtual void Reset() { _Current = NULL; _Next = _List->_Head; }
// 从列表中移除当前节点
virtual void Remove()
{
_List->Remove(_Current);
}
};
public:
// 返回一个循环访问集合的枚举数。外部释放
virtual IEnumerator<T>* GetEnumerator()
{
return new LinkedListEnumerator(this);
}
T& First() { return _Head->Item; }
T& Last() { return _Tail->Item; }
// 释放第一个有效节点
T& ExtractFirst()
{
if(!_Count) return NULL;
Node* node = _Head;
_Head = _Head->Next;
// 可能只有一个节点
if(!_Head)
_Tail = NULL;
else
_Head->Prev = NULL;
T& item = node->Item;
delete node;
_Count--;
return item;
}
// 释放最后一个有效节点
T& ExtractLast()
{
if(!_Count) return NULL;
Node* node = _Tail;
_Tail = _Tail->Prev;
// 可能只有一个节点
if(!_Tail)
_Head = NULL;
else
_Tail->Next = NULL;
T& item = node->Item;
delete node;
_Count--;
return item;
}
};
#endif //_List_H_