上一篇笔记中,分析了最底层的抽象类 VectorImpl
中的几个重点函数实现方法。可以看到在那个类中,基本上所有 Vector 应有的操作都已经实现好了。
而 SortedVectorImpl
则基于此,又针对 Sorted 这一特性而增加了一些底层操作,接下来就分析分析相关的代码实现。
文件路径:system\core\libutils\include\utils\VectorImpl.h
概览:
indexOf
(第 11 行):用于查找指定元素的位置。orderOf
(第 14 行):用于确定元素应插入的位置。add
(第 17 行):用于将元素加入 Vector 中正确的位置(如果已经有了,则覆盖)。merge
(第 20、21 行):用于合并 Vector。remove
(第 24 行):用于删除指定元素。do_compare
(第 27 行):纯虚函数,留给子类实现,应是用于确定比较规则的函数。_indexOrderOf
(第 30 行):用于确定元素应插入的位置(orderOf
的具体实现),其返回值表示元素所在位置(若无此元素则返回错误码),而参数 order
则返回所求的位置。SortedVector
这样的结构中不会提供给外部使用。class SortedVectorImpl : public VectorImpl
{
public:
SortedVectorImpl(size_t itemSize, uint32_t flags);
explicit SortedVectorImpl(const VectorImpl& rhs);
virtual ~SortedVectorImpl();
SortedVectorImpl& operator = (const SortedVectorImpl& rhs);
//! finds the index of an item
ssize_t indexOf(const void* item) const;
//! finds where this item should be inserted
size_t orderOf(const void* item) const;
//! add an item in the right place (or replaces it if there is one)
ssize_t add(const void* item);
//! merges a vector into this one
ssize_t merge(const VectorImpl& vector);
ssize_t merge(const SortedVectorImpl& vector);
//! removes an item
ssize_t remove(const void* item);
protected:
virtual int do_compare(const void* lhs, const void* rhs) const = 0;
private:
ssize_t _indexOrderOf(const void* item, size_t* order = 0) const;
// these are made private, because they can't be used on a SortedVector
// (they don't have an implementation either)
ssize_t add();
void pop();
void push();
void push(const void* item);
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
ssize_t appendArray(const void* array, size_t length);
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
};
文件路径:system\core\libutils\VectorImpl.cpp
这个类的实现部分内容比较少,也比较简单。
我认为此处值得关注的是:
_indexOrderOf
merge
查找逻辑:由于元素已经是排好序的,所以可以直接采用二分法进行查找。若查找不到指定元素,则将最终位置通过 order
返回,且函数返回值为错误码 NAME_NOT_FOUND
。若查找到元素,则返回其位置。
代码分析:
err
作为函数最终的返回值。l
表示当前需查找的区间的下界。h
表示当前需查找的区间的上界,此处 size
是父类函数,用于返回当前 Vector 的大小。而由于 Vector 下标从 0
开始,size - 1
才是其真正上界。mid
表示当前查找区间的中值。a
指向当前 Vector 的首地址(通过父类函数 arrayImpl
获取)。s
表示单个元素的大小(通过父类函数 itemSize
获取);mid = l + (h - l) / 2
,除法应是向下取整,如果区间元素数量为偶数,则计算出的中值应偏向下界。curr
指向中值所对应的元素地址。do_compare
(该函数由子类具体实现)比较 curr
与传入的指定元素 item
,这里分为三种情况。curr = item
,则查找成功,将变量 l
与 err
都赋值为 mid
(即成功查找时的下标)。curr < item
,则需要继续往上界方向查找(修改当前下界 l = mid + 1
)。curr > item
,则需要继续往下界方向查找(修改当前上界 h = mid - 1
)。order
非空(当不需要这个位置信息时,可以设置为空,或者令其缺省为空),则让其记录最终找到的位置。ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
{
if (order) *order = 0;
if (isEmpty()) {
return NAME_NOT_FOUND;
}
// binary search
ssize_t err = NAME_NOT_FOUND;
ssize_t l = 0;
ssize_t h = size()-1;
ssize_t mid;
const void* a = arrayImpl();
const size_t s = itemSize();
while (l <= h) {
mid = l + (h - l)/2;
const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
const int c = do_compare(curr, item);
if (c == 0) {
err = l = mid;
break;
} else if (c < 0) {
l = mid + 1;
} else {
h = mid - 1;
}
}
if (order) *order = l;
return err;
}
在看合并函数之前,可以先看看用于加入元素的 add
函数的实现:
_indexOrderOf
函数,获取待加入元素应插入的位置。index < 0
,表示原 Vector 中没有与 item
相同(怎样才算相同,取决于 do_compare
的具体实现)的元素,则在 order
指定的位置插入元素即可,Vector 保持已排序状态。index >= 0
,表示已经存在与 item
相同的元素,则用当前 item
把对应元素覆盖掉(以 Key-Value 形式的 Vector 为例,比较函数是通过 Key 进行比较的,则 item
对应的 Key-Value1 就会覆盖掉原来的 Key_Value0)。ssize_t SortedVectorImpl::add(const void* item)
{
size_t order;
ssize_t index = _indexOrderOf(item, &order);
if (index < 0) {
index = VectorImpl::insertAt(item, order, 1);
} else {
index = VectorImpl::replaceAt(item, index);
}
return index;
}
合并函数有两个,一个是针对一般的 VectorImpl
类型的 Vector,另一个是针对 SortedVectorImpl
类型的 Vector。
代码分析:
vector
中的每个元素,并通过 add
函数将其加入到当前 Vector 中。vector
的最后一个元素小于等于当前 Vector 的第一个元素,则在当前 Vector 的开头位置将其插入即可(通过调用父类函数 insertVectorAt
实现)。vector
的第一个元素大于等于当前 Vector 的最后一个元素,则往当前 Vector 末端将其加入即可(通过调用父类函数 appendVector
实现)。vector
的区间与当前 Vector 有重叠,此时就直接调用简单合并函数,依次将元素插入即可。ssize_t SortedVectorImpl::merge(const VectorImpl& vector)
{
// naive merge...
if (!vector.isEmpty()) {
const void* buffer = vector.arrayImpl();
const size_t is = itemSize();
size_t s = vector.size();
for (size_t i=0 ; i<s ; i++) {
ssize_t err = add( reinterpret_cast<const char*>(buffer) + i*is );
if (err<0) {
return err;
}
}
}
return NO_ERROR;
}
ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
{
// we've merging a sorted vector... nice!
ssize_t err = NO_ERROR;
if (!vector.isEmpty()) {
// first take care of the case where the vectors are sorted together
if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0);
} else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) {
err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector));
} else {
// this could be made a little better
err = merge(static_cast<const VectorImpl&>(vector));
}
}
return err;
}
VectorImpl
与 SortedVectorImpl
这两个抽象类都已经分析了一遍,接下来就要看看它们的子类 Vector
与 SortedVector
有哪些需要注意的了。实际上要关注的内容很少,因为各种功能都在抽象类中实现好了。