每天学一点算法-堆排序算法
来源:互联网 发布:西安西工大科信软件 编辑:程序博客网 时间:2024/05/13 06:21
堆的数据结构转化为数组的定义:
在起始索引为 0 的“堆”中:
1) 堆的根节点将存放在位置 02) 节点 i 的左子节点在位置 2 * i + 1
3) 节点 i 的右子节点在位置 2 * i + 2
4) 节点 i 的父节点在位置 floor( (i - 1) / 2 ) : 注 floor 表示“取整”操作
在起始索引为 1 的“堆”中:
1) 堆的根节点将存放在位置 1
2) 节点 i 的左子节点在位置 2 * i
3) 节点 i 的右子节点在位置 2 * i + 1
4) 节点 i 的父节点在位置 floor( i / 2 ) : 注 floor 表示“取整”操作
前人文章:http://blog.csdn.net/xiaoxiaoxuewen/article/details/7570621
堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:
Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]
即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。
重要:非叶子节点最大需要<=size/2;
根据上面的定义将图上的堆结构转换为数组后的形式为:
{11,9,10,5,8,2,6,4,3,1,7}
堆排序
定义
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
堆排序的平均时间复杂度为Ο(nlogn) 。
步骤
1.创建一个堆H[0..n-1]
2.把堆首(最大值)和堆尾互换
3.把堆的尺寸缩小1,并调用 shift_down (0),目的是把新的数组顶端数据调整到相应位置
4. 重复步骤2,直到堆的尺寸为1
时间复杂度
O(nlogn)
代码
package com.sprd.test.algorithm;import java.util.ArrayList;import java.util.List;/** * Copyright 2014 TJ SPREADTRUM TEST_AF All Right Reserved * * @author: hui.qian Created on 2014年11月26日 上午9:10:20 Description: */public class Heapsort {static List<Integer> sortedArray = new ArrayList<Integer>();public void sort(int[] data) {if (data.length == 1) {sortedArray.add(data[data.length - 1]);return;}// 队首和堆尾互换int temp = 0;temp = data[0];data[0] = data[data.length - 1];data[data.length - 1] = temp;// 堆的大小减1int[] newData = new int[data.length - 1];for (int i = 0; i < newData.length; i++) {newData[i] = data[i];}sortedArray.add(data[data.length - 1]);// 重新调整堆结构sort(parseHeap(newData));}public int[] parseHeap(int[] raw) {int length = raw.length;for (int i = length / 2; i >= 0; i--) {changeHeap(raw, i, length);}return raw;}// 调整堆让其符合结构性和有序性,即让最大的值处于堆根处public void changeHeap(int[] raw, int i, int size) {int leftIndex = 2 * i + 1;int rightIndex = 2 * i + 2;int max = i;if (i <= size / 2) {if (leftIndex < size && raw[leftIndex] > raw[max]) {max = leftIndex;}if (rightIndex < size && raw[rightIndex] > raw[max]) {max = rightIndex;}if (max != i) {int temp = 0;temp = raw[max];raw[max] = raw[i];raw[i] = temp;changeHeap(raw, i, size);}}}public static void main(String[] args) {Heapsort sorter = new Heapsort();// int[] raw = { 11, 9, 10, 5, 8, 2, 6, 4, 3, 1, 7 };int[] raw = { 9, 11, 10, 5, 8, 2, 6, 4, 3, 1, 7 };System.out.println("调整前 : ");print(raw);raw = sorter.parseHeap(raw);System.out.println("排序前 : ");print(raw);long start = System.currentTimeMillis();sorter.sort(raw);long end = System.currentTimeMillis();System.out.println("排序后 : ");printList(sortedArray);System.out.println("耗时 : " + (end - start));}public static void print(int[] datas) {for (int i = 0; i < datas.length; i++) {System.out.print(datas[i] + " ");}System.out.println("");}public static void printList(List<Integer> datas) {for (int i = 0; i < datas.size(); i++) {System.out.print(datas.get(i) + " ");}System.out.println("");}}
输出
调整前 : 9 11 10 5 8 2 6 4 3 1 7 排序前 : 11 9 10 5 8 2 6 4 3 1 7 排序后 : 11 10 9 8 7 6 5 4 3 2 1 耗时 : 0
0 0
- 每天学一点算法-堆排序算法
- 每天学一点算法-快速排序算法
- 每天学一点算法-归并排序算法
- 每天学一点算法-选择排序算法
- 每天学一点算法
- 每天学一点算法-DFS
- 每天学一点算法-BFS
- 每天学一点算法-Dijkstra算法
- 每天学一点算法-SPFA算法
- 每天学一点算法-二分查找算法
- 每天学一点算法-线性查找算法
- 每天学一点算法-动态规划算法
- 每天多一点算法-插入排序算法
- 一步一步学算法-堆排序
- 菜鸟学算法-----堆排序
- 每天学一点flash (41) 椭圆算法
- 每天学算法
- <菜鸟学算法-A排序(分治的思想:堆排序)>
- linux 命令—— source 详解
- Android - SQLite游标(Cursor)错误
- C++基础算法之 回文数
- freemarker 异常和错误显示
- Android程序员必备精品资源
- 每天学一点算法-堆排序算法
- Android - Activity类和Manager类的更新通信
- Java学习笔记——文件存在检测
- opengl GLSL 学习 随笔三
- 写在前言之前
- PHP mysql_fetch_array($result)
- 基于物联网的高速铁路检测系统研究
- Android - 错误:Unable to instantiate application
- 所有创业者都必须注意的一个策略