学习算法导论——堆排序
2016-03-01 11:31
405 查看
《算法导论》第三版书中数组下标是从1开始的,但是这里从0开始。
最小堆和最大堆刚好相反。
首先要了解的一些知识是对于根节点i,其左孩子节点为2*i+1,右孩子节点为2*i+2;第一个非叶节点为(n-2)/2;其中n为数组大小。
下面的Max_Heapily()函数是使得根节点为i的树(子树)为最大堆
![](https://img-blog.csdn.net/20160301161302831)
只有上面图片中的是三个节点不符合最大堆时,它才会调整子树。
结果:
![](https://img-blog.csdn.net/20160301112905697)
![](https://img-blog.csdn.net/20160301150404790)
另一种创建最大堆的方法为插入法,我们可以这样想像,将数组中的元素按顺序逐个插入一个二叉树中,如插入A[0]为根节点,接着插入A[1]为左孩子节点并和根节点A[0]比较,如果不符合最大堆,则A[1]和根节点A[0]交换值;同样,插入A[2];插入A[3],和根节点A[1]比较,如果不符合最大堆,A[3]和A[1]交换值,此时,还需要继续往“总根”方向比较,比较A[1]和A[0],根据最大堆的性质决定是否要交换值,其他节点插入同理。
插入法创建最大堆C++代码:
1.堆定义
堆分为两种,即最大堆和最小堆,最大堆的定义为:当数组A大小为n时(A中有n个元素),若2*i+1<n有A[i]>=A[2*i+1];若2*i+2<n有A[i]>=A[2*i+2],则这样的数据结构称为最大堆。说白了就是根节点(包括子树的根节点)的值不小于左节点和右节点的值(如果有左或右节点的话)。最小堆和最大堆刚好相反。
2.创建最大堆
这里以最大堆为例。首先要了解的一些知识是对于根节点i,其左孩子节点为2*i+1,右孩子节点为2*i+2;第一个非叶节点为(n-2)/2;其中n为数组大小。
unsigned Left_Child(unsigned i) { return 2 * i + 1; }
unsigned Right_Child(unsigned i) { return 2 * i + 2; }
下面的Max_Heapily()函数是使得根节点为i的树(子树)为最大堆
void Max_Heapily(unsigned A[], unsigned i,unsigned n)//维持根节点为i的树为最大堆 { unsigned l = Left_Child(i); unsigned r = Right_Child(i); unsigned largest=i; if (l < n && A[l] > A[largest]) largest = l; if (r < n && A[r]>A[largest]) largest = r; if (largest != i) { unsigned temp = A[i]; A[i] = A[largest]; A[largest] = temp; Max_Heapily(A, largest,n);//递归调整子树 } }
void Build_Max_Heap(unsigned A[], unsigned n)//从第一个非叶节点到根节点调整为最大堆 { for (int i = (n - 2) / 2; i >= 0; --i) { Max_Heapily(A, i, n); } }上面的Build_Max_Heap()函数为什么从第一个非叶节点开始循环?因为根据最大堆的定义,不但整课树为最大堆,所有的子树也为最大堆,第一个非叶节点就是第一颗子树的根节点。存在疑问的地方是,那直接Max_Heapily(A,0,n)不就行了吗?不行,该函数调整的是根节点和左右孩子节点:
只有上面图片中的是三个节点不符合最大堆时,它才会调整子树。
3.堆排序算法
首先,把有n个元素的数组A初始化创建为最大堆,然后循环执行如下过程直到数组为空为止:(1)把堆顶A[0]元素(为最大元素)和当前最大堆的最后一个元素交换;(2)最大堆元素个数减1;(3)由于第(1)步后根节点不再满足最大堆的定义,所以调整根节点使之满足最大堆的定义。void Heap_Sort(unsigned A[],unsigned n) { Build_Max_Heap(A,n); for (unsigned i = n - 1; i > 0; --i) { unsigned temp = A[0]; A[0] = A[i]; A[i] = temp; Max_Heapily(A, 0, --n); } }
int main(int argc, char* argv[]) { unsigned A[10] = {4,1,3,2,16,9,10,14,8,7}; Heap_Sort(A, 10); for (unsigned i = 0; i < 10; ++i) { std::cout << A[i] << " "; } getchar(); return 0; }
结果:
另一种创建最大堆的方法为插入法,我们可以这样想像,将数组中的元素按顺序逐个插入一个二叉树中,如插入A[0]为根节点,接着插入A[1]为左孩子节点并和根节点A[0]比较,如果不符合最大堆,则A[1]和根节点A[0]交换值;同样,插入A[2];插入A[3],和根节点A[1]比较,如果不符合最大堆,A[3]和A[1]交换值,此时,还需要继续往“总根”方向比较,比较A[1]和A[0],根据最大堆的性质决定是否要交换值,其他节点插入同理。
插入法创建最大堆C++代码:
void Max_Heap_Insert(unsigned A[], unsigned position) { unsigned P=position; unsigned parent = (position - 1) / 2; while (P > 0 && A[parent] < A[P]) { unsigned temp = A[P]; A[P] = A[parent]; A[parent] = temp; P = parent; parent = (P - 1) / 2; } }
void Build_Max_Heap(unsigned A[],unsigned n) { for (unsigned i = 1; i < n; ++i) { Max_Heap_Insert(A, i); } }
相关文章推荐
- iframe跨域上传图片
- Mac 已经安装多个版本的XCode,现又安装了XCode7.2.1报错
- syslog-ng解析dns,引起dhcpd 工作失效!
- UITabBarController
- 纪录一下最近被微信坑的事情
- iOS开发之Runloop
- MapServer 之 发布网络覆盖数据服务(WCS-Web Coverage Service)
- oracle监听理解 命名理解
- 简单的封装继承多态
- Adobe Dreamweaver CC 2014 代码颜色目录
- 兼容ie6及以上的阴影滤镜的写法
- 字符串对象(NSString)常用方法
- PHP学习(一):对PHP的理解
- 理解文章《Notes on Convolutinal Neural Networks》
- elasticsearch2.2-yarn(hadoop)安装
- Android中数据持久化的三种方式
- OpenGL ES着色器语言之着色概览(官方文档第二章)
- iOS 第三方库冲突的处理
- JAVA学习之GUI组件中Toolkit的使用
- maven3常用命令、java项目搭建、web项目搭建详细图解