您好,登錄后才能下訂單哦!
堆排序(heapsort)是一種比較快速的排序方式,它的時間復雜度為O(nlgn),并且堆排序具有空間原址性,任何時候只需要有限的空間來存儲臨時數據。我將用c++實現一個堆來簡單分析一下。
堆排序的基本思想為:
1、升序排列,保持大堆;降序排列,保持小堆;
2、建立堆之后,將堆頂數據與堆中最后一個數據交換,堆大小減一,然后向下調整;直到堆中只剩下一個有效值;
下面我將簡單分析一下:
第一步建立堆:
1、我用vector順序表表示數組;
2、用仿函數實現大小堆隨時切換,實現代碼復用;
3、實現向下調整算法,時間復雜度為O(lgn);
下面是我用某教材中的一個建最小堆的過程圖,希望能更直觀一些:
為了保證復用性,用仿函數重載了(),下面是復用的向下調整算法:
void _AdjustDown(int root,int size) { Camper camper; //仿函數 int parent = root; int child = parent * 2 + 1; while (child <= size) //保證訪問不越界 { if (child < size && camper(_vec[child+1] , _vec[child])) //保證存在右子樹、同時判斷右子樹是否大于或小于左子樹 { child++; } if (camper(_vec[child], _vec[parent])) { swap(_vec[parent], _vec[child]); parent = child; child = parent * 2 + 1; } else { break; } } }
排序算法思想:
1、將堆頂數據與堆中最后一個數據交換;
2、堆大小減一,然后調用向下調整算法;
3、結束條件:堆中剩下一個有效值;
排序算法實現:
void Sort() { size_t size = _vec.size(); //數據數量 while (size > 1) { swap(_vec[0], _vec[size - 1]); size--; _AdjustDown(size); } }
仿函數的實現:
template<class T> struct Greater //大于 { bool operator ()(const T& l, const T& p) { return l > p; } }; template<class T> struct Less //小于 { bool operator () (const T&l, const T& p) { return l < p; } };
完整的代碼實現:
#include<iostream> using namespace std; #include<vector> template<class T> struct Greater //大于 { bool operator ()(const T& l, const T& p) { return l > p; } }; template<class T> struct Less //小于 { bool operator () (const T&l, const T& p) { return l < p; } }; template<class T,class Camper> class HeapSort //建大堆 { public: HeapSort() {} HeapSort(T* arr, size_t n) { _vec.reserve(n); if (arr != NULL) { for (size_t i = 0; i < n; i++) { _vec.push_back(arr[i]); } } _AdjustDown(_vec.size()); } void Sort() { size_t size = _vec.size(); //數據數量 while (size > 1) { swap(_vec[0], _vec[size - 1]); size--; _AdjustDown(size); } } void Print() { for (size_t i = 0; i < _vec.size(); i++) { cout << _vec[i] <<" "; } cout << endl; } protected: void _AdjustDown(int size) { int parent = (size - 2) / 2; while (parent >= 0) { _AdjustDown(parent, size - 1); parent--; } } void _AdjustDown(int root,int size) { Camper camper; //仿函數 int parent = root; int child = parent * 2 + 1; while (child <= size) //保證訪問不越界 { if (child < size && camper(_vec[child+1] , _vec[child])) //保證存在右子樹、同時判斷右子樹是否大于或小于左子樹 { child++; } if (camper(_vec[child], _vec[parent])) { swap(_vec[parent], _vec[child]); parent = child; child = parent * 2 + 1; } else { break; } } } private: vector<T> _vec; };
測試用例代碼:
void TextSort() { int a[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 }; HeapSort<int,Greater<int>> h(a, sizeof(a) / sizeof(a[0])); h.Print(); h.Sort(); h.Print(); }
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。