C++ 數(shù)據(jù)結(jié)構(gòu) 堆排序的實現(xiàn)
堆排序(heapsort)是一種比較快速的排序方式,它的時間復(fù)雜度為O(nlgn),并且堆排序具有空間原址性,任何時候只需要有限的空間來存儲臨時數(shù)據(jù)。我將用c++實現(xiàn)一個堆來簡單分析一下。
堆排序的基本思想為:
1、升序排列,保持大堆;降序排列,保持小堆;
2、建立堆之后,將堆頂數(shù)據(jù)與堆中最后一個數(shù)據(jù)交換,堆大小減一,然后向下調(diào)整;直到堆中只剩下一個有效值;
下面我將簡單分析一下:
第一步建立堆:
1、我用vector順序表表示數(shù)組;
2、用仿函數(shù)實現(xiàn)大小堆隨時切換,實現(xiàn)代碼復(fù)用;
3、實現(xiàn)向下調(diào)整算法,時間復(fù)雜度為O(lgn);
下面是我用某教材中的一個建最小堆的過程圖,希望能更直觀一些:
為了保證復(fù)用性,用仿函數(shù)重載了(),下面是復(fù)用的向下調(diào)整算法:
void _AdjustDown(int root,int size) { Camper camper; //仿函數(shù) 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、將堆頂數(shù)據(jù)與堆中最后一個數(shù)據(jù)交換;
2、堆大小減一,然后調(diào)用向下調(diào)整算法;
3、結(jié)束條件:堆中剩下一個有效值;
排序算法實現(xiàn):
void Sort() { size_t size = _vec.size(); //數(shù)據(jù)數(shù)量 while (size > 1) { swap(_vec[0], _vec[size - 1]); size--; _AdjustDown(size); } }
仿函數(shù)的實現(xiàn):
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; } };
完整的代碼實現(xiàn):
#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(); //數(shù)據(jù)數(shù)量 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; //仿函數(shù) 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(); }
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
上一篇:通過先序遍歷和中序遍歷后的序列還原二叉樹(實現(xiàn)方法)
欄 目:C語言
本文標(biāo)題:C++ 數(shù)據(jù)結(jié)構(gòu) 堆排序的實現(xiàn)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/1482.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計- 解析最少換車次數(shù)的問題詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計-用棧實現(xiàn)表達(dá)式求值的方法詳解
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實現(xiàn)與遞歸實現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10深入理解堆排序及其分析


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機閱讀
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實例總結(jié)
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 08-05DEDE織夢data目錄下的sessions文件夾有什