前面四篇文章主要学习“Ordered List”,本文将学习另一种列表(list)—— “Sorted List”。
一、“Sorted List”的特性和声明(点击打开链接)
“Sorted List”与“Ordered List”类似,都是保存一系列元素的可搜索容器。不同的是, “Sorted List”中任一项的位置不是任意的,它的全部项都是按从小到大的顺序排列的。它的order符合“total order”(点击打开链接)。
“Sorted List”的接口是在“Searchable Container”的基础上,增加了“FindPosition”、“operator[]”和“Withdraw”三个接口。这些接口的实现与“Ordered List”也非常相似。当然,也可以看出来, “Sorted List”没有“InsertAfter”和“InsertBefore”,因为它的全部项位置不是任意的。因此,“Sorted List”相对其基类不增加新接口,它的实现除“FindPosition”、“operator[]”和“Withdraw”外,都可以复用“Ordered List”的实现。
接口声明如下:
class SortedList : public List { };
先来看“Sorted List”的数组实现。为了提高代码复用,我们采用“多继承”的方式来实现它:继承“Sorted List”的接口和继承“ListAsArray”的实现。声明如下:
#pragma once #include "ListAsArray.h" class SortedListAsArray : public virtual SortedList, public virtual ListAsArray { public: SortedListAsArray(unsigned int); ~SortedListAsArray(); void Insert(Object &); Object & operator[](unsigned int) const; Object & operator[](Position const &) const; Object & Find(Object const &) const; Position & FindPosition(Object const &) const; void Withdraw(Object &); void Withdraw(Position const &); private: unsigned int FindOffset(const Object&) const; };
实现代码如下:
#include "stdafx.h" #include "SortedListAsArray.h" #include "NullObject.h" SortedListAsArray::SortedListAsArray(unsigned int _size) : ListAsArray(_size) { } SortedListAsArray::~SortedListAsArray() { } void SortedListAsArray::Insert(Object & object) { if (count == array.Length()) throw std::domain_error("list is full"); unsigned int i = count; while (i > 0 && *array[i-1U] > object) { array[i] = array[i - 1U]; --i; } array[i] = &object; ++count; } Object & SortedListAsArray::operator[](unsigned int offset) const { return ListAsArray::operator[](offset); } Object & SortedListAsArray::operator[](Position const & arg) const { return ListAsArray::operator[](arg); } Object & SortedListAsArray::Find(Object const & object) const { const unsigned int offset = FindOffset(object); if (offset < count) return *array[offset]; else return NullObject::Instance(); } Position & SortedListAsArray::FindPosition(Object const & object) const { unsigned int offset = FindOffset(object); return *new Pos(*this, offset); } void SortedListAsArray::Withdraw(Object & object) { if (count == 0) throw std::domain_error("list is empty"); const unsigned int offset = FindOffset(object); if (offset == count) throw std::invalid_argument("object is not found"); for (unsigned int i = offset; i < count - 1U; ++i) array[i] = array[i + 1]; --count; } void SortedListAsArray::Withdraw(Position const & arg) { ListAsArray::Withdraw(arg); } unsigned int SortedListAsArray::FindOffset(const Object& object) const { int left = 0; int right = count - 1; while (left <= right) { const int middle = (left + right) / 2; if (object > *array[middle]) left = middle + 1; else if (object < *array[middle]) right = middle - 1; else return middle; } return count; }
2,“FindOffset”是一个辅助函数,它采用“binary search”算法,查找“Sorted List”中特定元素的位置。(点击打开链接),它的时间复杂度是O(logn)。此外,它采用的是值相等的匹配策略。
3,其他函数需要借助“FindOffset”来实现。
三、测试
// test for SortedListAsArray { SortedListAsArray list1(10); Int pArray[] = { Int(16), Int(2), Int(3), Int(14), Int(5) }; for (unsigned int i = 0; i < 5; ++i) list1.Insert(pArray[i]); list1.Put(std::cout); for (unsigned int i = 0; i < 5; ++i) list1.Withdraw(list1.FindPosition(pArray[i])); //list1.Withdraw(pArray[i]); }