排序之代理類(三十三)

        我們在之前學習了各種排序的算法,那麼我們的排序類(Sort)和數組類(Array)之間的關係如下。

圖片.png

        那麼我們需要將排序類和數組類之間關聯起來,怎麼進行關聯呢?我們需要在排序類中新增幾個成員函數,具體函數原型如下

圖片.png

        具體代碼如下,我們在 Array.h 中添加如下代碼

T* array() const
{
    return m_array;
}

        上面函數用來獲取 array 的頭地址。Sort.h 代碼如下

template <typename T>
static void Select(Array<T>& array, bool min2max = true)
{
    Select(array.array(), array.length(), min2max);
}

template <typename T>
static void Insert(Array<T>& array, bool min2max = true)
{
    Insert(array.array(), array.length(), min2max);
}

template <typename T>
static void Bubble(Array<T>& array, bool min2max = true)
{
    Bubble(array.array(), array.length(), min2max);
}

template <typename T>
static void Shell(Array<T>& array, bool min2max = true)
{
    Shell(array.array(), array.length(), min2max);
}

template <typename T>
static void Merge(Array<T>& array, bool min2max = true)
{
    Merge(array.array(), array.length(), min2max);
}

template <typename T>
static void Quick(Array<T>& array, bool min2max = true)
{
    Quick(array.array(), array.length(), min2max);
}

        我們在 main.cpp 中添加如下測試代碼

#include <iostream>
#include "Sort.h"
#include "StaticArray.h"

using namespace std;
using namespace DTLib;

int main()
{
    StaticArray<int, 5> sa;

    for(int i=0; i<5; i++)
    {
        sa[i] = i;
    }

    Sort::Bubble(sa, false);

    for(int i=0; i<5; i++)
    {
        cout << sa[i] << endl;
    }
    
    return 0;
}

        排序結果如下

圖片.png

        我們看到已經正確進行排序。那麼在排序的工程應用中,有個經典的問題:那就是當待排數據元素爲體積龐大的對象時,我們應如何提高排序的效率呢?我們以下來的示例代碼作爲分析

#include <iostream>
#include <ctime>
#include "Sort.h"

using namespace std;
using namespace DTLib;

struct Test : public Object
{
    int id;
    int data1[1000];
    double data2[500];

    bool operator < (const Test& obj)
    {
        return id < obj.id;
    }

    bool operator >= (const Test& obj)
    {
        return id >= obj.id;
    }

    bool operator > (const Test& obj)
    {
        return id > obj.id;
    }

    bool operator <= (const Test& obj)
    {
        return id <= obj.id;
    }
};

Test t[1000];

int main()
{
    clock_t begin = 0;
    clock_t end = 0;

    for(int i=0; i<1000; i++)
    {
        t[i].id = i;
    }

    begin = clock();

    Sort::Bubble(t, 1000, false);

    end = clock();

    cout << "Time : " << (end - begin) << endl;

    return 0;
}

        我們來看看花費的時間,結果如下

圖片.png

        我們看到花費時間很長。那麼我們來分析下。在排序過程中,要不可避免的進行交換操作;然而交換操作的本質是數據元素間的相互複製,如當數據元素體積較大時,交換操作耗時巨大。我們來看看經典的做法:代理模式。

        1、爲待排數據元素設置代理對象;

        2、對代理對象所組成的序列進行排序;

        3、需要訪問有序數據元素時,通過訪問代理序列完成。

        也就是說,我們通過操作代理對象進而來操作原來的數據對象。如下:

圖片.png

        代理效果如下圖所示

圖片.png

        我們看到用小對象數據來代替大對象數據,具體代碼如下

#include <iostream>
#include <ctime>
#include "Sort.h"

using namespace std;
using namespace DTLib;

struct Test : public Object
{
    int id;
    int data1[1000];
    double data2[500];

    bool operator < (const Test& obj)
    {
        return id < obj.id;
    }

    bool operator >= (const Test& obj)
    {
        return id >= obj.id;
    }

    bool operator > (const Test& obj)
    {
        return id > obj.id;
    }

    bool operator <= (const Test& obj)
    {
        return id <= obj.id;
    }
};

class TestProxy : public Object
{
protected:
    Test* m_pTest;
public:
    int id()
    {
        return m_pTest->id;
    }

    int* data1()
    {
        return m_pTest->data1;
    }

    double* data2()
    {
        return m_pTest->data2;
    }

    Test& test() const
    {
        return *m_pTest;
    }

    bool operator < (const TestProxy& obj)
    {
        return test() < obj.test();
    }

    bool operator >= (const TestProxy& obj)
    {
        return test() >= obj.test();
    }

    bool operator > (const TestProxy& obj)
    {
        return test() > obj.test();
    }

    bool operator <= (const TestProxy& obj)
    {
        return test() <= obj.test();
    }

    Test& operator = (Test& test)
    {
        m_pTest = &test;

        return test;
    }
};

Test t[1000];
TestProxy pt[1000];

int main()
{
    clock_t begin = 0;
    clock_t end = 0;

    for(int i=0; i<1000; i++)
    {
        t[i].id = i;
        pt[i] = t[i];
    }

    begin = clock();

    Sort::Bubble(pt, 1000, false);

    end = clock();

    cout << "Time : " << (end - begin) << endl;

    return 0;
}

        結果如下

圖片.png

        我們看到效率提高了50倍左右,這就是經典的代理類模式。我們通過對代理類的學習,總結如下:1、當排序體積是很龐大的對象時,使用代理模式間接完成;2、代理模式的使用有效避開大對象交換時的耗時操作;3、代理模式解決方案是空間換時間思想的體現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章