考研数据结构笔记—堆排序
完全二叉树是效率很高的数据结构,堆是一种完全二叉树或者近似完全二叉树,所以效率同样极高。目前十分常用的排序算法、Dijkstra算法、Prim算法等都要用堆才能优化。
堆排序是一种选择排序算法,与原序列的初始排列次序无关,即最好、最坏和一般情况排序的时间复杂度不变,均为O(nlgn)。而且,堆排序只需要一个记录元素大小的辅助空间(供交换使用),故空间复杂度为O(1)。正由于堆排序不仅时间复杂度小,而且空间复杂度O(1)也是最小,所以是用于排序的最佳选择。
堆的定义
n个元素序列 { k0,k1,..., kn } 当且仅当满足下列条件之一时,称之为堆(其中 i = 0, 1, ..., n/2 向下取整)。
- ki <= k2i+1 且 ki <= k2i+2(最小堆)
- ki >= k2i+1 且 ki >= k2i+2(最大堆)
堆排序实现
利用最大堆性质实现堆排序
#include <iostream> using namespace std; /*交换数组中两个元素的值*/ void Swap(int *arr, int a, int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } /*(大根)堆调整*/ void maxHeapify(int *arr, int length, int curNode) { /*找出当前节点和其左右节点三者的最大值*/ int maxNode = curNode; int left = curNode * 2 + 1; int right = curNode * 2 + 2; if (left < length && arr[left] > arr[maxNode]) //左孩子存在且较大 maxNode = left; if (right < length && arr[right] > arr[maxNode]) //右孩子存在且较大 maxNode = right; if (maxNode != curNode) //当前节点不是最大则需要交换 { Swap(arr, maxNode, curNode); maxHeapify(arr, length, maxNode); //子节点需重新调整 } } /*(最大)堆排序 *思想: *1、构建最大堆 *2、从最后一个元素开始只第二个元素将依次与首元素交换 *3、进行数组中当前元素前面的所有元素的局部调整堆 *上面步骤2和步骤3将所有元素都与首元素交换,将局部范围内的最大值沉到后面,然后进行当前元素前面所有元素的局部范围内的堆调整 *即在数组A中,当前元素索引为i,将A[i]与A[0]交换,将A[0,1,...,i]中最大的值放到A[i],然后进行A[0,1,...,i-1]堆调整, *将A[0,1,...,i-1]内的最大值放到A[0]中,待下一次交换使用,实现将局部的最大值依次沉到数组后面,完成排序 */ void heapSort(int *arr, int length) { //构建堆 for (int i = length / 2 - 1; i >= 0; i--) //从最后一个非叶节点开始 { maxHeapify(arr, length, i); } for (int i = length - 1; i > 0; i--) { Swap(arr, 0, i); //与首元素交换 maxHeapify(arr, i, 0); //调整堆 } } int main() { cout << "堆排序算法实现" << endl; int data[] = { 6,8,2,3,9,7,4,1,5,10 }; cout << "排序之前的数据:"; for (int i = 0; i<10; i++) cout << data[i] << " "; cout << endl; heapSort(data, 10); cout << "排序之后的数据:"; for (int i = 0; i<10; i++) cout << data[i] << " "; cout << endl; system("pause"); return 0; }
堆排序优化实现,重新理解
#ifndef _HEAP_SORT_H #define _HEAD_SORT_H class heapsort { public: void sort(int *a, int len) { if (len <= 1){ return; } //建堆,保证头结点为数组最大值 createHeap(a, len); /* * 从数组最后一位开始,依次递减, a[i]和头结点交换,即a[i]等于a[0~i]中最大值 * 前i-1个元素再堆化 * 这样数组每一个位置i都能得到a[0~i]中的最大值 * 最后使得整个数组有序 */ for (int i=len-1; i>0; --i) { swap(a[0], a[i]); heapify(a, i-1, 0); } } private: void createHeap(int *a, int len) { for (int i = len/2 - 1; i>=0; --i) { heapify(a, len-1, i); } } void heapify(int *a, int n, int i) { while (true) { int maxPos = i; int left = i * 2 + 1; int right = i * 2 + 2; if (left <= n && a[left] > a[maxPos]) { maxPos = left; } if (right <= n && a[right] > a[maxPos]) { maxPos = right; } if (maxPos == i) { break; } swap(a[i], a[maxPos]); i = maxPos; } } void swap(int& a, int& b) { int tmp = a; a = b; b = tmp; } }; #endif