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

        前面四篇文章主要学习“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”。
数据结构之“Ordered List and Sorted List”(五)_第1张图片

实现代码如下:

#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”算法,极大提高访问效率。

你可能感兴趣的:(数据结构之“Ordered List and Sorted List”(五))