堆排序
2016-07-04 16:21
232 查看
思想
堆是什么?堆是一个数组,它可以被看成一个近似的完全二叉树,树上的每一个结点对应数组中的一个元素。除去最底层外,该树是完全充满的,而且从左到右填充。
堆分为大顶堆和小顶堆
大顶堆:结点 i 的值 都大于其左右孩子结点的值
小顶堆:结点 i 的值 都小于其左右孩子结点的值
如何建堆?
建堆的过程是一个不断将元素插入到堆的过程。这里的插入过程,和插入排序很类似,插入排序重点是找到插入的位置,找到位置后更新该位置值。对于堆,重要的位置有三个:left,right,parent,对当前i位置,其左孩子位置left,右孩子位置right,当插入 i 位置的元素时候,当 i 位的元素 比left和right位置的元素大,i位置符合大顶堆的条件,不需要调整,当i位置的元素和left、right位置元素比较时候不是最大值,需要调整堆
如何调整堆?
最大位置id元素和i位置处的元素进行交换,交换后可能不是大顶堆了,这时候需要调整的位置就是交换后的最大位置id元素,这就是一个递归的过程。
如何堆排序?
堆已经建立好了,0号位置是最大值,但是这个堆不一定是有序的,其只是满足 parent大于left right位置的值,所以,把0号位置元素和最后位置进行交换,然后调整0号位置使得是大顶堆。
结点
public int parent(int i){ int p = (i-1)/2; return p; } public int left(int i){ int l = i*2+1; return l; } public int right(int i){ int r = i*2+2; return r; }
插入元素
插入新元素调整为大顶堆递归算法
/** * i 位置元素插入到堆中,调整为大顶堆 * 递归实现 * @param A * @param n * @param i */ public void heap(int[] A,int n,int i){ // 左孩子 int l = left(i); // 右孩子 int r = right(i); // 最大结点下标 int largest = -1; // i l r 找到最大值的下标,找到后进行交换 if(l<=n && A[l] >A[i]) largest = l; else largest = i; if(r<=n && A[r]>A[largest]) largest = r; if(largest!=i){ swap(A,largest,i); // 最大值下标和i处值进行交换 heap(A,n,largest); // 交换后,largest 所在的子树也应该是大顶堆,下面一个递归的过程了 } }
时间复杂度:O(log2(n))O(log_2(n))
循环算法
public void heap1(int[] A,int n,int i){ // 左孩子 int l = left(i); // 右孩子 int r = right(i); // 最大结点下标 int largest = -1; // i l r 找到最大值的下标,找到后进行交换 if(l<=n && A[l] >A[i]) largest = l; else largest = i; if(r<=n && A[r]>A[largest]) largest = r; while(largest!=i){ swap(A,largest,i); i = largest; l = left(i); r = right(i); if(l<=n && A[l] >A[i]) largest = l; else largest = i; if(r<=n && A[r]>A[largest]) largest = r; } }
public void swap(int[] A,int i,int j){ int tmp= A[i]; A[i] = A[j]; A[j] = tmp; }
建堆
/** * 建堆是自底向上的过程 * @param A * @param n */ public void buildMaxHeap(int[] A,int n){ for(int i=n/2;i>=0;i--){ heap1(A,n,i); } }
堆排序
public void heapSort(int[] A){ int n = A.length - 1; buildMaxHeap(A,n);// 建立大顶堆,0 位置是最大值 for(int i =n;i>=1;i--){ swap(A,i,0); // 0 位置是最大值,调整为升序,0位置元素和局部最大id位置进行交换 heap1(A,i-1,0); // 交换后,可能不是大顶堆,进行调整 } }
主函数
public static void main(String[] args) { int[] A = new int[]{49,38,65,97,76,13,27,49}; Print.printArray(A); HeapSort heapSort = new HeapSort(); heapSort.heapSort(A); Print.printArray(A); }
输出
49 38 65 97 76 13 27 49 13 27 38 49 49 65 76 97
复杂度分析
(1)时间复杂度O(nlog2(n))O(nlog_2(n))
(2)空间复杂度
O(1)O(1)
参考
1.cnblogs
相关文章推荐
- hdwiki 编码规范
- Jquery 遍历数组之$().each方法与$.each()方法介绍
- json.load(f)方法使用*.json备忘
- 竖直ProgressBar(VerticalProgressBar),不用那么麻烦
- J2MEWTK提供六种模拟器
- 让iOS开发变得更有效率-分类、工具类
- 自定义View之交替圆环
- 读书笔记-java网络编程-4Internet-InetAddress类
- 图表部件设置X轴节点的错位显示
- 判断二叉树是否为平衡二叉树(BST)
- 114. Flatten Binary Tree to Linked List
- 判断当前星期几
- C#简单查询SQLite数据库是否存在数据的方法
- Logstash使用grok过滤nginx日志(二)
- Git简单用法
- Android中使用Handler造成内存泄露的分析和总结
- 卡特兰数知识
- JavaScript Promise 实现(三)
- java语言基础入门——变量、数据及常量的介绍
- 交换机吃v喝奶粉v