diff --git a/inc/hgl/type/DataArray.h b/inc/hgl/type/DataArray.h index 0e8771a..e678a87 100644 --- a/inc/hgl/type/DataArray.h +++ b/inc/hgl/type/DataArray.h @@ -49,6 +49,14 @@ namespace hgl return count-vil.count; } + void SetData(T *data,int64 data_count) + { + Free(); + + items=data; + alloc_count=count=data_count; + } + public: /** @@ -174,6 +182,15 @@ namespace hgl return items[n]; } + void Append(const T &obj) + { + if(count>=alloc_count) + Alloc(count+1); + + items[count]=obj; + ++count; + } + T *At(int64 n)const { return (n<0||n>=count)?nullptr:items+n; diff --git a/inc/hgl/type/IndexedList.h b/inc/hgl/type/IndexedList.h new file mode 100644 index 0000000..668ed99 --- /dev/null +++ b/inc/hgl/type/IndexedList.h @@ -0,0 +1,409 @@ +#pragma once + +#include +#include + +namespace hgl +{ + /** + * 索引数据列表
+ * IndexedList与ArrayList功能类似,但它的区别是它使用索引来访问数据。 + * 当数据被移动、删除、排序时,数据本身的内存并不会变动,只会调整索引。 + */ + template class IndexedList + { + protected: + + DataArray data_array; + DataArray data_index; + Stack free_index; + + public: //属性 + + const int32 GetAllocCount ()const{return data_array.GetAllocCount();} + const int32 GetCount ()const{return data_index.GetCount();} + const int32 GetFreeCount ()const{return free_index.GetCount();} + + const size_t GetTotalBytes ()const{return data_index.GetCount()*sizeof(T);} + + const bool IsEmpty ()const{return data_index.IsEmpty();} + + bool PreAlloc(int32 count) + { + if(count<=0)return(false); + + data_array.Alloc(count); + data_index.Alloc(count); + + return(true); + } + + public: // 迭代器 + + class Iterator + { + private: + + IndexedList *list; + int32 current_index; + + public: + + using iterator_category = std::forward_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using reference = T&; + + public: + + Iterator(const IndexedList* lst, int32 idx):list(lst),current_index(idx){} + + T& operator*() const + { + return list->data_array[list->data_index[current_index]]; + } + + Iterator &operator++(){current_index++;return *this;} + Iterator operator++(int){Iterator tmp=*this;++(*this);return tmp;} + + Iterator &operator--(){current_index--;return *this;} + Iterator operator--(int){Iterator tmp=*this;--(*this);return tmp;} + + bool operator==(const Iterator &other) const + { + return current_index==other.current_index; + } + + bool operator!=(const Iterator &other) const + { + return current_index!=other.current_index; + } + };//class Iterator + + Iterator begin() const + { + return Iterator(this,0); + } + + Iterator end() const + { + return Iterator(this,data_index.GetCount()); + } + + Iterator last() const + { + return Iterator(this,data_index.GetCount()-1); + } + + public: + + IndexedList()=default; + IndexedList(const T *lt,const int n){Add(lt,n);} + IndexedList(const IndexedList <){operator=(lt);} + IndexedList(const std::initializer_list <){operator=(lt);} + virtual ~IndexedList(){Free();} + + /** + * 向列表中添加一个空数据 + * @return 这个数据的指针 + */ + virtual T *Add() + { + if(free_index.IsEmpty()) + { + data_array.AddCount(1); + return data_array.last(); + } + else + { + int32 index; + + free_index.Pop(index); + data_index.Append(index); + + return data_array.At(index); + } + } + + /** + * 向列表中添加一个数据对象 + * @param data 要添加的数据对象 + * @return 这个数据的索引号 + */ + virtual int32 Add(const T &data) + { + int32 index; + + if(free_index.IsEmpty()) + { + index=data_array.GetCount(); + + data_array.AddCount(1); + data_index.Append(index); + } + else + { + free_index.Pop(index); + data_index.Append(index); + } + + hgl_cpy(data_array[index],data); + return index; + } + + /** + * 向列表中添加一批数据对象 + * @param data 要添加的数据对象 + * @param n 要添加的数据数量 + * @return 添加了几个 + */ + virtual int32 Add(const T *data,int n) + { + if(!data||n<=0) + return(-1); + + const int32 fc=free_index.GetCount(); + + int32 result=0; + + if(fc>0) //如果有剩余的空间 + { + const int32 mc=hgl_min(fc,n); + + int32 index=data_array.GetCount(); + + data_array.AddCount(n); + data_index.AddCount(n); + + for(int32 i=0;i(data_array[index],data[i]); + } + + n-=mc; + data+=mc; + + result=mc; + } + + //剩余空间没了 + + if(n>0) //如果还有,那就整段添加吧 + { + int32 index=data_array.GetCount(); + + data_array.AddCount(n); + data_index.AddCount(n); + + for(int32 i=0;i(data_array.At(index),data,n); + + result+=n; + } + + return result; + } + + virtual void Clear() + { + data_array.Clear(); + data_index.Clear(); + free_index.Clear(); + } + + virtual void Free() + { + data_array.Free(); + data_index.Free(); + free_index.Free(); + } + + const bool IsValidIndex(const int32 index)const + { + return !(index<0||index>=data_index.GetCount()); + } + + /** + * 删除数据 + * @param start 起始删除的数据索引 + * @param count 删除个数 + * @return 删除成功的数据个数 + */ + virtual int32 DeleteAt(int32 start,int32 count=1) + { + if(!IsValidIndex(start)return(-1); + if(count<=0)return(count); + + if(start+count>data_index.GetCount()) + count=data_index.GetCount()-start; + + if(count<=0)return(0); + + for(int32 i=start;i sorted_index(count); + Stack overflow_index; + Stack space_location; + + overflow_index.PreAlloc(count); + space_location.PreAlloc(count); + + hgl_cpy(sorted_index.GetData(),data_index.GetData(),count); + + std::sort(sorted_index.GetData(),count,sizeof(int32),[](const void *a,const void *b) + { + return *(int32 *) a-*(int32 *) b; + }); + + //查找空的位置 + { + int32 *p=sorted_index.GetData(); + + for(int i=0;i=count) + { + overflow_index.Push(i); + } + + ++p; + } + } + + if(overflow_index.IsEmpty()) + return(true); + + if(overflow_index.GetCount()!=space_location.GetCount()) + return(false); + + //直接将超出边界的数据移到空的位置上,并更新索引 + { + int32 new_location; + int32 index; + + while(space_location.Pop(new_location)) + { + overflow_index.Pop(index); + + hgl_cpy(data_array.At(new_location),data_array.At(data_index[index])); + + data_index[index]=new_location; + } + } + + free_index.Clear(); + return(true); + } + + /** + * 当前数据是否顺序排好的 + */ + const bool IsOrdered()const + { + const int count=data_index.GetCount(); + const int32 *p=data_index.GetData(); + + for(int i=0;i(count); + + int i = 0; + while (i < count) + { + int start = i; // 当前连续块的起始位置 + int end = i; // 当前连续块的结束位置 + + // 检查后续索引是否是连续的正确顺序 + while (end + 1 < count && data_index[end + 1] == data_index[end] + 1) + { + ++end; + } + + // 批量复制连续块的数据 + int length = end - start + 1; + hgl_cpy(temp_array+start, data_array.GetData() + data_index[start], length); + + // 更新索引 + i = end + 1; + } + + // 将临时数组的数据复制回 data_array + data_array.SetData(temp_array,count); + + // 更新 data_index,使其与 data_array 的顺序一致 + for (int i = 0; i < count; ++i) + { + data_index[i] = i; + } + } + };//template class IndexedList +}//namespace hgl