算法学习导论学习笔记-第6章 堆排序
2010-07-24 15:36
429 查看
6.1 堆
堆是一种完全二叉树,因此可以用数组A来表示。树的根为A[1],给定了某个结点的下标i,其父结点PARENT(i)、左儿子LEFT(i)、右儿子RIGHT(i)的下标可以简单地计算出来:PARENT(i)
return i/2
LEFT(i)
return 2i
RIGHT(i)
return 2i+1
二叉堆有两种:最大堆和最小堆。在这两种堆中,结点内的数值都要满足heap property。在最大堆中,max-heap property是指除了根结点以外的每个结点i,有
A[PARENT(i)] >= A[i]
在最小堆中,min-heap property是指除了根结点以外的每个结点i,有
A[PARENT(i)] <= A[i]
6.2 保持堆的性质
MAX-HEAPIFY是对最大堆进行操作的重要子程序。其输入为一个数组A和下标i。当MAX-HEAPIFY被调用时,我们假定以LEFT(i)和RIGHT(i)为根的两棵二叉树都是最大堆,但这时A[i]可能小于其子女,这样就违反了max-heap property。MAX_HEAPIFY让A[i]在最大堆中“下降”,使以i为根的子树成为最大堆。MAX-HEAPIFY(A,i) l = LEFT(i) r = RIGHT(i) if l <= heap-size[A] and A[l] > A[i] then largest = l else largest = i if r <= heap-size[A] and A[r] > A[largest] then largest = r if largest != i then exchange A[i],A[largest] MAX-HEAPIFY(A,largest)
当MAX-HEAPIFY作用在一棵以结点i为根的,大小为n的子树上时,其时间复杂度为O(lgn)。
6.3 建堆
我们可以自底向上地用MAX-HEAPIFY来将一个数组A[1..n]变成一个最大堆。BUILD-MAX-HEAP(A) heap-size[A] = length[A] for i = length[A]/2 downto 1 do MAX-HEAPIFY(A,i)
BUILD-MAX-HEAP的时间复杂度是O(n)。
6.4 堆排序算法
HEAPSORT(A) BUILD-MAX-HEAP(A) for i from length[A] downto 2 do exchange A[1],A[i] heap-size[A] = heap-size[A] – 1 MAX-HEAPIFY(A,1)
HEAPSORT的时间复杂度为O(nlgn)。其中 BUIDL-MAX-HEAP的时间为O(n), n-1次HEAP-MAX-HEAPIFY调用中每一次的时间代价为O(lgn)。
6.5 优先级队列
HEAP-MAXIMUM(A) return A[1]
时间为0(1)
HEAP-EXTRACT-MAX(A) if heap-size[A] < 1 then error “heap underflow” max = A[1] A[1] = A[heap-size[A]] heap-size[A] = heap-size[A] – 1 MAX-HEAPIFY(A,1) return max
时间复杂度为O(lgn)。
HEAP-INCREASE-KEY(A,i,key) if key < A[i] then error “new key is smaller than current key” A[i] = key while i>1 and A[PARENT(i)] < A[i] do exchange A[i],A[PARENT(i)] i = A[PARENT(i)]
时间复杂度为O(lgn)
MAX-HEAP-INSERT(A,key) heap-size[A] = heap-size[A] + 1 A[heap-size[A]] = –MAX HEAP-INCREASE-KEY(A,heap-size[A],key)
时间复杂度为O(lgn)
堆排序C实现:
#include <stdio.h> #define Left(i) ((i) << 1) #define Right(i) (((i) << 1) + 1) #define Parent(i) ((i) >> 1) void swap(int *x,int *y) { int temp; temp = *x; *x = *y; *y = temp; } void max_heapity(int a[],int i,int heapsize) { int largest,left,right; left = Left(i); right = Right(i); largest = i; if(left <= heapsize && a[left] > a[i]) largest = left; if(right <= heapsize && a[right] > a[largest]) largest = right; if(largest != i) { swap(&a[i],&a[largest]); max_heapity(a,largest,heapsize); } } void build_max_heap(int a[],int heapsize) { int i; for(i = heapsize / 2; i >= 1; i--) max_heapity(a,i,heapsize); } void heap_sort(int a[],int heapsize) { int i; build_max_heap(a,heapsize); for(i = heapsize; i>=2; i--) { swap(&a[1],&a[i]); heapsize--; max_heapity(a,1,heapsize); } } int main() { int a[] = {0,10,19,8,7,6,5,4,3,2,1,12,14,9}; int heapsize = 13; int i; printf("before sort:"); for(i = 1; i <= heapsize; i++) printf(" %d",a[i]); printf("/n"); heap_sort(a,heapsize); printf("after sort:"); for(i = 1; i <= heapsize; i++) printf(" %d",a[i]); printf("/n"); }
相关文章推荐
- 算法导论学习笔记 第6章 堆排序
- 【算法导论】学习笔记——第6章 堆排序
- 算法学习笔记----第二部分:排序和顺序统计量----第6章、堆排序
- 算法学习笔记----第二部分:排序和顺序统计量----第6章、堆排序
- 算法导论学习笔记-第九章-中位数和顺序统计学
- <算法导论>学习笔记 第一部分 第1章 算法在计算中的作用
- 算法导论学习笔记-第五章-概率分析和随机算法
- 算法导论学习笔记——基数排序
- 【算法导论】学习笔记——第10章 基本数据结构
- 算法导论学习笔记(8)——动态规划之矩阵链乘法
- 【算法导论】学习笔记——第7章 快速排序
- 算法导论学习笔记-第2章 算法入门
- 麻省理工算法导论学习笔记(5)----线性时间排序
- 【算法导论学习笔记】第2章:算法基础
- 算法导论学习笔记-5.4 概率分析和指示器随机变量的应用-几个有趣的问题
- Introduction to Algorithms 算法导论 第3章 函数的增长 学习笔记及习题解答
- 算法学习笔记之堆排序
- 算法导论学习笔记 第2章 算法基础
- 【算法导论】学习笔记——第22章 图的基本算法
- 算法导论课——动态规划学习笔记