《算法导论》读书笔记--堆排序

来源:互联网 发布:mac自带放大镜快捷键 编辑:程序博客网 时间:2024/04/30 05:40

预备知识:

堆通常被看做一个近似完全的二叉树,使用数组A[1...N]表示堆,数组中一个元素代表堆上一个结点,堆存在以下性质:

根节点:A[1]

父结点:Parent[i] = i/2

左子节点:Left[i] = 2i

右子节点:Right[i] = 2i + 1

数组长度为:A.length

数组中有效数据长度为:A.heap-size

堆分为最大堆和最小堆,在最大堆中 Parent[i] >= A[i],在最小堆中 Parent[i]  <= A[i]


维护堆的性质(MAX-HEAPIFY):调节父结点与子结点位置,使他们满足最大堆的大小关系。将A[i]的值在最大堆中“逐级下降”,从而使以下标i为根结点的子树重新遵循最大堆的性质。

MAX-HEAPIFY(A,i)l = Left[i]r = Right[i]if l <= A.heap-size and A[l] > A[i]    lagest = lelse    lagest = iif r <= A.heap-size and A[r] > A[lagest]    lagest = rif i != lagest //当根结点不是最大值时    exchage A[i] with A[lagest]    MAX-HEAPIFY(A,lagest)//交换位置后,以该结点为根的子树可能违法最大堆的性质,所以需要递归调用

时间复杂度为:T(n) <= T(2/3n)+O(1) 根据主定理公式可以计算出 时间复杂度为O(lgn)


建堆(BUILD-MAX-HEAP):将无序的数组转换为最大堆。

BUILD-MAX-HEAP(A)A.heap-size = A.length for i = [A.heap-size/2] downto 1 //此处i的值为A.heap-size/2向下取整的值,因为A[A.heap/2+1...A.heap-size]为叶子结点,没有子结点,所以只需考虑前半部分的值    MAX-HEAPIFY(A,i)
时间复杂度为 O(n)


堆排序算法(HEAPSORT):因为建堆后,数组中的数据并不是有序的,但最大值一定位于根结点A[1],根据此性质,可以进行排序

HEAPSORT(A)    BUILD-MAX-HEAP(A)    for i = A.length downto 2 //不断将最大值放在堆中最后一个元素位置,对应就是数组中由后向前进行排序        exchange A[1] with A[i] //将最大元素置后        A.heap-size = A.heap-size - 1 //有效长度减1,表示该元素已经归位        MAX-HEAPIFY(A,1) //因为将原堆末尾元素提到了根结点,所以需要对根结点重新执行MAX-HEAPIFY维护堆的性质。
时间复杂度为O(nlogn)

Demo:

#include <iostream>#include <stdio.h>using namespace std;#define LENGTH 10int heap_size = 0;void swap(int *a,int *b){int tmp;tmp = *a;*a = *b;*b = tmp;}void max_headpify(int *A,int i)//维护堆的性质,下沉元素{int lagest;int l = i*2;int r = i*2+1;if((l <= heap_size) && (A[l] > A[i]))lagest = l;else lagest = i;if((r <= heap_size) && (A[r] > A[lagest]))lagest = r;if(lagest != i){swap(&A[i],&A[lagest]);max_headpify(A,lagest);}}void build_max_heap(int *A)//构建堆{heap_size = LENGTH;for(int i = LENGTH/2;i >= 1;i--)max_headpify(A,i);}void heapsort(int *A)//堆排序{build_max_heap(A);for(int i = LENGTH;i >= 2;i--){ swap(&A[1],&A[i]);heap_size--;max_headpify(A,1);}}int main(){int A[LENGTH+1];for(int i = 1;i <= LENGTH;i++){cin>>A[i];}heapsort(A);for(int i = 1;i <= LENGTH;i++){printf("%d\n",A[i]);}system("pause");return 0;}



0 0
原创粉丝点击