[数据结构与算法]堆排序 Heap Sort
来源:互联网 发布:企业名录搜索软件 编辑:程序博客网 时间:2024/06/05 08:21
堆的定义
n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。
情形1:ki <= k2i 且ki <= k2i+1 (最小化堆或小顶堆)
情形2:ki >= k2i 且ki >= k2i+1 (最大化堆或大顶堆)
其中i=1,2,…,n/2向下取整;
若将和此序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。
由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。
例如,下列两个序列为堆,对应的完全二叉树如图:
若在输出堆顶的最小值之后,使得剩余n-1个元素的序列重又建成一个堆,则得到n个元素的次小值。如此反复执行,便能得到一个有序序列,这个过程称之为堆排序。
堆排序(Heap Sort)只需要一个记录元素大小的辅助空间(供交换用),每个待排序的记录仅占有一个存储空间。
堆的存储
一般用数组来表示堆,若根结点存在序号0处, i结点的父结点下标就为(i-1)/2。i结点的左右子结点下标分别为2*i+1和2*i+2。
(注:如果根结点是从1开始,则左右孩子结点分别是2i和2i+1。)
如第0个结点左右子结点下标分别为1和2。
如最大化堆如下:
左图为其存储结构,右图为其逻辑结构。
存储在堆内的数据由Node类来构建。
public class Node { public int data; public Node(int key) { data = key; } }通过吧节点插入到堆数组内的方式可以构造堆,二堆数组的元素就是堆的节点。
这里始终要把新节点放置在数组末尾的空元素内。问题是这样做很可能会打破堆的构造条件,因为新的节点的数据值可能会大于他上面某些节点值。为了把数组恢复到正确的堆构造条件,需要把新节点向上移动,一直要把它移动到数组内合适的位置上为止。用ShifUp来实现。
public void ShifUp(int index) { int parent = (index - 1) / 2; Node bottom = heapArray[index]; while ((index > 0) && heapArray[index].data < bottom.data) { heapArray[index] = heapArray[parent]; index = parent; parent = (parent - 1) / 2; } heapArray[index] = bottom; }下面是Insert方法的实现代码:
public bool Insert(int key) { if (currSize == maxSize) return false; heapArray[currSize] = new Node(key); currSize++; return true; }这里会把新节点添加到数组的末尾。这样做会立刻打破堆构造的条件,所以通过shifup方法来找到新节点在数组内的正确位置。次方法的参数就是新节点的索引。方法的第一行会计算此节点的父节点。接着方法会把新节点保存到一个名为bottom的Node变量内。随后,wihle循环会找到新节点的正确位置。方法的最后一行会把新节点从临时放置的变量bottom内复制到数组中正确的位置上。
从堆中移除掉节点始终意味着删除最大值的节点。这是很容易实现的,因为最大值始终在根节点上。问题是一旦移除根节点,堆就不完整了,就需要对其进行重组。下面这个算法用于使堆再次完整。
(1)移除根节点
(2)把最后位置上的节点移动到根上
(3)把最后的节点向下移动,知道它在底下为止。
当连续应用这个算法的时候,就会按照排列顺序把数据从堆中移除掉。下面就是Remove方法和TrickleDown方法的实现代码。
public Node Remove() { Node root = heapArray[0]; currSize--; heapArray[0] = heapArray[currSize]; ShifDown(0); return root; } public void ShifDown(int index) { int largerChild; Node top = heapArray[index]; while (index < (int)(currSize / 2)) { int leftChild = 2 * index + 1; int rightChild = leftChild + 1; if ((rightChild < currSize) && heapArray[leftChild].data < heapArray[rightChild].data) { largerChild = rightChild; } else { largerChild = leftChild; } if (top.data >= heapArray[largerChild].data) { break; } heapArray[index] = heapArray[largerChild]; index = largerChild; } heapArray[index] = top; }完整:
class Heap { Node[] heapArray = null; private int maxSize = 0; private int currSize = 0; public Heap() { } public Heap(int maxSize) { this.maxSize = maxSize; heapArray = new Node[maxSize]; } public bool InsertAt(int pos, Node nd) { heapArray[pos] = nd; return true; } public void ShowArray() { for (int i = 0; i < maxSize; i++) { if (heapArray[i] != null) { System.Console.Write(heapArray[i].data+" "); } } } public void ShifUp(int index) { int parent = (index - 1) / 2; Node bottom = heapArray[index]; while ((index > 0) && heapArray[index].data < bottom.data) { heapArray[index] = heapArray[parent]; index = parent; parent = (parent - 1) / 2; } heapArray[index] = bottom; } public bool Insert(int key) { if (currSize == maxSize) return false; heapArray[currSize] = new Node(key); currSize++; return true; } public Node Remove() { Node root = heapArray[0]; currSize--; heapArray[0] = heapArray[currSize]; ShifDown(0); return root; } public void ShifDown(int index) { int largerChild; Node top = heapArray[index]; while (index < (int)(currSize / 2)) { int leftChild = 2 * index + 1; int rightChild = leftChild + 1; if ((rightChild < currSize) && heapArray[leftChild].data < heapArray[rightChild].data) { largerChild = rightChild; } else { largerChild = leftChild; } if (top.data >= heapArray[largerChild].data) { break; } heapArray[index] = heapArray[largerChild]; index = largerChild; } heapArray[index] = top; } public void Test() { const int SIZE = 9; Heap aHeap = new Heap(SIZE); Random RandomClass = new Random(); for (int i = 0; i < SIZE; i++) { int rn = RandomClass.Next(1,100); aHeap.Insert(rn); } Console.Write("Random: "); aHeap.ShowArray(); Console.WriteLine(); Console.Write("Heap: "); for(int i=(int)SIZE/2-1;i>=0;i--) { aHeap.ShifDown(i); } aHeap.ShowArray(); for (int i = SIZE - 1; i >= 0; i--) { Node bigNode = aHeap.Remove(); aHeap.InsertAt(i,bigNode); } Console.WriteLine(); Console.Write("Sorted: "); aHeap.ShowArray(); } }
- [数据结构与算法]堆排序 Heap Sort
- 【数据结构-堆排序】堆排序 Heap Sort
- 算法----堆排序(heap sort)
- 经典排序算法 - 堆排序Heap sort
- 经典排序算法 - 堆排序Heap sort
- 经典排序算法 - 堆排序Heap sort
- 经典排序算法 - 堆排序Heap sort
- 选择排序算法:堆排序-Heap Sort
- 排序算法---堆排序(Heap Sort)
- 堆排序(Heap Sort)算法的实现
- 堆排序(Heap Sort)算法学习
- 堆排序(Heap Sort)算法的实现
- 堆排序(Heap Sort)算法学习
- 堆排序(Heap Sort)
- 堆排序(Heap Sort)
- 堆排序(Heap Sort)
- 堆排序 (Heap Sort)
- 堆排序(Heap Sort)
- leaflet中maker添加mouseover事件
- solve: vmware audit:backlog limit exceeded
- wps表格或excel表格怎样转换成为PDF文件
- 有关于cocos js加载网络图片
- java图形验证码工具类
- [数据结构与算法]堆排序 Heap Sort
- 10 个你有可能不知道的Android Studio技巧
- mac 版mybatis-generator eclipse 插件在线安装
- design包8种控件
- leaflet中给maker添加mouseover、mouseout、click
- 2016-Q4目标
- C#继承相关
- JAVA从菜鸟【入门】到新手【实习】一一计算机网络技术
- Eclipse中的debug模式的快捷键