我们在之前学习了各种排序的算法,那么我们的排序类(Sort)和数组类(Array)之间的关系如下。
那么我们需要将排序类和数组类之间关联起来,怎么进行关联呢?我们需要在排序类中新增几个成员函数,具体函数原型如下
具体代码如下,我们在 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; }
排序结果如下
我们看到已经正确进行排序。那么在排序的工程应用中,有个经典的问题:那就是当待排数据元素为体积庞大的对象时,我们应如何提高排序的效率呢?我们以下来的示例代码作为分析
#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; }
我们来看看花费的时间,结果如下
我们看到花费时间很长。那么我们来分析下。在排序过程中,要不可避免的进行交换操作;然而交换操作的本质是数据元素间的相互复制,如当数据元素体积较大时,交换操作耗时巨大。我们来看看经典的做法:代理模式。
1、为待排数据元素设置代理对象;
2、对代理对象所组成的序列进行排序;
3、需要访问有序数据元素时,通过访问代理序列完成。
也就是说,我们通过操作代理对象进而来操作原来的数据对象。如下:
代理效果如下图所示
我们看到用小对象数据来代替大对象数据,具体代码如下
#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; }
结果如下
我们看到效率提高了50倍左右,这就是经典的代理类模式。我们通过对代理类的学习,总结如下:1、当排序体积是很庞大的对象时,使用代理模式间接完成;2、代理模式的使用有效避开大对象交换时的耗时操作;3、代理模式解决方案是空间换时间思想的体现。