我們在之前學習了各種排序的算法,那麼我們的排序類(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、代理模式解決方案是空間換時間思想的體現。