算法 -- 堆排序
算法(堆排序)
这里的堆是指二叉堆, 二叉堆就是一种满足堆的两个特性的一颗完全二叉树,也叫优先队列。(区别于内存的堆。)
理解链接:http://www.cnblogs.com/zabery/archive/2011/07/26/2117103.html
时间复杂度
O(n*log(n)),
其他堆:
二叉堆
二项堆
斐波那契堆
对类型: 最小堆和最大堆

原理:
1. 现在数组是一个堆的形式:如下图(7个) 2. 循环n次(即从7开始倒循环),每次循环都会在根上得到最值,把最值与数组尾交换(1与7交换) 3. 2步骤中的循环一次循环m/2次(7/2),循环之后再根上得到最值 4. 2步骤循环结束就排序完毕了 for(m=n;n>0;n--) { for(i=m/2;i>0;i--) }
操作:插入,删除,排序
warn:
模板中类的函数声明与定义需都写在同一文件下
下面实现中,插入删除操作影响类的对象数据(如:mHeap),不影响传入的数组(如:arr)。
排序造作指影响传入的数据(如:arr)
以下是代码实现
#pragma once /** * 二叉堆 * * @author skywang * @date 2014/03/07 */ #include <iomanip> #include <iostream> using namespace std; template <class T> class HeapSort{ private: /* * 当插入或删除数据时,数组长度产生变化,创建容器数组辅助实现 (mHeap) */ T *mHeap; // 数据 int mCapacity; // 数组容量(总) int mSize; // 实际容量 private: // 建堆(将最值置顶) = (n/2)次(sortAdjust) void BuildHeap(T arr[], int len, bool bDesc); void sortAdjust(T arr[], int len, int cur, bool bDesc); public: // 构造函数 HeapSort(); HeapSort(int capacity); ~HeapSort(); // 直接数组进行排序(排序的数组, 数组长度, 是否倒排序) int filtersort(T arr[], int len, bool bDesc); // 直接返回data在二叉堆中的索引 int getIndex(T arr[], int len, T data); // 删除最大堆中的data(吃操作将影响成员数据) int remove(T arr[], int len, T data, bool bDesc); // 将data插入到二叉堆中(吃操作将影响成员数据) int insert(T arr[], int len, T data, bool bDesc); // 删除插入后,数据存储在成员变量中,提供函数供外部调用 T* getHeap(); int getSize(); //(默认输出mHeap)打印数组 void print(); void print(T arr[], int len); }; /* * ********************************************************* * 构造函数 * ********************************************************* */ template <class T> HeapSort<T>::HeapSort() { new (this)HeapSort(30); } /* * 带参构造函数 */ template <class T> HeapSort<T>::HeapSort(int capacity) { mSize = 0; mCapacity = capacity; mHeap = new T[mCapacity]; } /* * 析构函数 */ template <class T> HeapSort<T>::~HeapSort() { msize = 0; mcapacity = 0; delete[] mHeap; } /* ********************************************************** * 堆排序 start ********************************************************** */ template <class T> void HeapSort<T>::BuildHeap(T arr[], int len, bool bDesc) { int i; int begin = len/2; //最后一个非叶子节点 for (i = begin; i >= 0; i--) { this->sortAdjust(arr, len, i, bDesc); } } template <class T> void HeapSort<T>::sortAdjust(T arr[], int len, int cur, bool bDesc) { int left = cur*2; int right = cur*2+1; int parent = cur; int size = len; int temp; if(bDesc) { if(left < size && arr[parent] > arr[left]) parent = left; if(right < size && arr[parent] > arr[right]) parent = right; } else { if(left < size && arr[parent] < arr[left]) parent = left; if(right < size && arr[parent] < arr[right]) parent = right; } if(cur != parent) { //交换父节点和和拥有最大值的子节点交换 temp = arr[parent]; arr[parent] = arr[cur]; arr[cur] = temp; } } /* * 需要排序的数组 返回值: * 0,表示成功 * -1,表示失败 */ template <class T> int HeapSort<T>::filtersort(T arr[], int len, bool bDesc) { int t_len = len; int temp; while (t_len>0) { this->BuildHeap(arr, t_len, bDesc); temp = arr[t_len-1]; arr[t_len-1] = arr[0]; arr[0] = temp; t_len --; } return 0; } /****** 堆排序 end ******************************************* /* * 删除最大堆中的data, 数组长度改变,依赖类成员数据操作 * 插入后排序的数据存储在该对象成员变量内(mHeap, mCapacity, mSize), 同时不影响传入的数组数据 */ template <class T> int HeapSort<T>::remove(T arr[], int len, T data, bool bDesc) { int index; // 如果"堆"已空,则返回-1 if(len == 0) return -1; // 获取data在数组中的索引 index = getIndex(arr, len, data); if (index==-1) return -1; //将数据存储到该对象中 if(mCapacity<len) { mCapacity = len; delete[] mHeap; mHeap = new T[mCapacity]; } this->mSize = len; for(int i=0;i<mSize;i++) mHeap[i] = arr[i]; mHeap[index] = mHeap[--mSize]; // 用最后元素填补 this->filtersort(mHeap, mSize, bDesc); return index; } /* * 将data插入到二叉堆中 * 插入后排序的数据存储在该对象成员变量内(mHeap, mCapacity, mSize),同时不影响传入的数组数据 */ template <class T> int HeapSort<T>::insert(T arr[], int len, T data, bool bDesc) { //将数据存储到该对象中 if(mCapacity<len+1) { mCapacity = len+1; delete[] mHeap; mHeap = new T[mCapacity]; } this->mSize = len; for(int i=0;i<mSize;i++) { mHeap[i] = arr[i]; } // 如果"堆"已满,则返回 if(mSize == mCapacity) return -1; mSize++; mHeap[mSize-1] = data; // 将"数组"插在表尾 //排序并获取 index this->filtersort(mHeap, mSize, bDesc); int index = getIndex(mHeap, mSize, data); return index; } /* * 返回data在二叉堆中的索引 * * 返回值: * 存在 -- 返回data在数组中的索引 * 不存在 -- -1 */ template <class T> int HeapSort<T>::getIndex(T arr[], int len, T data) { for(int i=0; i<len; i++) if (data==arr[i]) return i; return -1; } /** * 获取数据,数组大小 **/ template <class T> T* HeapSort<T>::getHeap() { return mHeap; } template <class T> int HeapSort<T>::getSize() { return mSize; } template <class T> void HeapSort<T>::print() { for (int i=0; i<mSize; i++) cout << i << ":" << mHeap[i] << " "; cout << endl; } /* * 数组打印 arr(数组), len(长度) */ template <class T> void HeapSort<T>::print(T arr[], int len) { for (int i=0; i<len; i++) cout << i << ":" << arr[i] << " "; cout << endl; }
调用
int _tmain(int argc, _TCHAR* argv[]) { int a[] = {10, 40, 30, 60, 90, 75, 70, 20, 50, 80}; int len=(sizeof(a)) / (sizeof(a[0])) ; HeapSort<int>* tree=new HeapSort<int>(); // 排序 tree->filtersort(a, len, NULL); tree->print(a, len); // 查询 int index = tree->getIndex(a, len, 40); cout << "查询:" << index << endl; // 删除后,数据数据存储在MaxHeap中 int index_r = tree->remove(a, len, 40, true); cout << "删除:" << index_r << endl; tree->print(); // 插入 int index_i = tree->insert( a, len, 35, true); cout << "插入:" << index_i << endl; tree->print(); //================================= system("pause"); return 0; }
THE END
浙公网安备 33010602011771号