您的位置:首页 > 理论基础 > 数据结构算法

数据结构之“Ordered List and Sorted List”(五)

2016-03-07 13:53 316 查看
前面四篇文章主要学习“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
{
};


二、SortedListAsArray

先来看“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;
};


注:“Purge”、“Accept”、“IsMemeber”和“CompareTo”直接继承自“ListAsArray”。



实现代码如下:

#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;
}


1,“Insert”函数采用的还是“移位”的方法,它将找位置和移位放到一个循环中进行实现。

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]);
}


注:采用数组实现的“Sorted List”可以应用“Binary Search”算法,极大提高访问效率。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: