理解二叉堆数据结构及Swift的堆排序算法实现示例_Swift

二叉堆的性质
1.二叉堆是一颗完全二叉树,最后一层的叶子从左到右排列,其它的每一层都是满的
2.最小堆父结点小于等于其每一个子结点的键值,最大堆则相反
3.每个结点的左子树或者右子树都是一个二叉堆
下面是一个最小堆:

堆的存储
通常堆是通过一维数组来实现的。在起始数组为 0 的情形中:
1.父节点i的左子节点在位置 (2*i+1);
2.父节点i的右子节点在位置 (2*i+2);
3.子节点i的父节点在位置 floor((i-1)/2);

维持堆的性质
我们以最大堆来介绍(后续会分别给出最大堆和最小堆的实现).所谓维持堆得性质就是字面意思,也就是确保叶子节点和父节点的关系是堆得关系; 那么怎么维持呢?

这里我们是以某一个节点为起始点,调整其自身与子节点的关系,使得父节点总是大于子节点,处理完毕后递归操作调整后的节点;
我们来看一下具体的实现:

/**
* 维护最大堆的性质
*/
func heapify(inout A:[Int], i:Int, size:Int) {
 var l = 2 * i
 var r = l + 1
  var largest = i

 if l < size && A[l] > A[i] {
 largest = l
 }
  if r < size && A[r] > A[largest] {
    largest = r
  }
  if largest != i {
    swap(&A, i, largest)
    heapify(&A, largest, size)
  }
}

有效代码也就10行上下, 简单解释下,根据传入的节点在数组内的索引,计算出左右子节点,然后比较比较子节点的值大小,将大的值对调为父节点的值,最后递归处理新节点;

构建堆
现在来看第二步,也就是构建一个堆。我们的输入数据源是一个以为数组,需要通过构建,将其以堆的性质加以调整; 我们来看一下具体的实现:

/**
* 构建最大堆
*/
func buildHeap(inout A:[Int]) {
  for var i = A.count/2; i >= 0; i-- {
    heapify(&A, i, A.count)
  }
  println("build heap:\(A)")
}

简单解释下,根据上一步已经得到的维护堆性质的函数,我们队数组内的所有非叶子节点遍历,针对每个节点都做一遍堆处理,最后得到的就是一个完整的堆; 可能不理解的骚年会问了,为什么数组遍历不是全量的,而是[A.count/2, 0]?
这个问题,我想最好的的答案是你画一个二叉树,一眼就能明白,这棵树中非叶子节点的索引就是count/2;

堆排序

现在重温一下,这个经典的堆排序是怎么实现的。
以算法导论中对堆排序的介绍,可以简单的归结为三句话:
1.维持堆的性质
2.构建堆
3.堆排序
好,终于到了见证奇迹的时刻,我们把数组排个序输出一下。

/**
*堆排序
*/
func heapSort(inout A:[Int]) {
  buildHeap(&A)
  var size = A.count
  for var i = A.count - 1; i >= 1; i-- {
    swap(&A, i, 0)
    size--
    heapify(&A, 0, size)
  }
  println("sorted heap:\(A)")
}

这里呢,需要注意的地方就是每次得到最大值后,我们需要把问题的解规模减小,因为我们是原址排序,实际上是把一维数组分为了未排序的堆和已排序的数组两部分,已排序的部分放在数组尾部;

验证一下
随便搞个数组,我们排个队

var A = [4, 1, 3, 2, 16, 9,9, 10, 14, 8, 7]
heapSort(&A)
avens-MacBook-Pro:aven$ ./max-heap-sort.swift
build heap:[16, 14, 9, 10, 8, 7, 9, 2, 3, 1, 4]
sorted heap:[1, 2, 3, 4, 7, 8, 9, 9, 10, 14, 16]

小结
上面我们已经完成了最大堆的算法的编码,最小堆也是类似的; 算法这东西如果能理解的话写起来就不太难,所以一定要对理论有所了解,真正理解了算法思路才能吧思路写成代码。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索swift
, 堆排序
, 排序算法
二叉堆
二叉树 堆排序、二叉树排序和堆排序、完全二叉树堆排序、完全二叉树最小堆排序、堆排序算法,以便于您获取更多的相关知识。

时间: 2024-09-13 19:45:14

理解二叉堆数据结构及Swift的堆排序算法实现示例_Swift的相关文章

数据结构 之 二叉堆(Heap)

注:本节主要讨论最大堆(最小堆同理). 一.堆的概念     堆,又称二叉堆.同二叉查找树一样,堆也有两个性质,即结构性和堆序性.     1.结构性质:     堆是一棵被完全填满的二叉树,有可能的例外是在底层,底层上的元素从左到右填入.这样的树称为完全二叉树(complete binary tree).下图就是这样一个例子.         对于完全二叉树,有这样一些性质:     (1).一棵高h的完全二叉树,其包含2^h ~ (2^(h+1) - 1)个节点.也就是说,完全二叉树的高是[

数据结构-二叉堆(C描述)

1.主要的存储结构 struct HeapStruct { int Capacity;//最大容量 int Size;//当前容量 ElementType *Elements;//数组入口地址 }; typedef struct HeapStruct *PriorityQueue; 结构体HeapStruct实际上是一个数组,二叉堆的底层实现是一个完全二叉树,因此可以很方便的使用数组实现. 完全二叉树的一个重要性质是可以明确给出父子之间的位置关系: 设节点v的秩为i(设根节点秩为0),则 若v有

在A*寻路中使用二叉堆

A*算法中最缓慢的部分就是在开启列表中寻找F值最低的节点或者方格.取决于地图的大小,你可能有十几,成百甚至上千的节点需要在某个时候使用A*搜索.无需多讲,反复搜索这么大的列表会严重拖慢整个过程.然而,这些时间在极大程度上受你存储列表的方式影响. 有序和无序的开启列表:简单的方法 最简单的方法就是顺序存储每个节点,然后每次需要提取最低耗费元素的时候都遍历整个列表.这提供可快速的插入速度,但是移除速度可能是最慢的,因为你需要检查每个元素才能够确定哪个才是F值最低的. 通常你可以保持你列表处于有序状态

二叉堆(binary heap)

堆(heap) 亦被称为:优先队列(priority queue),是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.在队列中,调度程序反复提取队列中第一个作业并运行,因而实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权.堆即为解决此类问题设计的一种数据结构. 本文地址:http://www.cnblogs.com/archimedes/p/binary-heap.html,转载请注明源地址. 逻辑定义 n个

优先队列之二叉堆与d-堆

二叉堆简介   平时所说的堆,若没加任何修饰,一般就是指二叉堆.同二叉树一样,堆也有两个性质,即结构性和堆序性.正如AVL树一样,对堆的以此操作可能破坏者两个性质中的一个,因此,堆的操作必须要到堆的所有性质都被满足时才能终止. 结构性质   堆是一棵完全填满的二叉树,因为完全二叉树很有规律,所以它可以用一个数组表示而不需要指针.如下图所示,图2中的数组对应图1中的堆.                              图1:二叉堆                             

结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆、斜堆

实现优先队列结构主要是通过堆完成,主要有:二叉堆.d堆.左式堆.斜堆.二项堆.斐波那契堆.pairing 堆等.   1. 二叉堆  1.1. 定义 完全二叉树,根最小. 存储时使用层序.   1.2. 操作 (1). insert(上滤) 插入末尾 26,不断向上比较,大于26则交换位置,小于则停止.   (2). deleteMin(下滤) 提取末尾元素,放在堆顶,不断下滤:   (3). 其他操作: 都是基于insert(上滤)与deleteMin(下滤)的操作. 减小元素:减小节点的值,

二叉堆

容易证明: 一棵高为h的完全二叉树有2^h 到 2^(h+1)-1个结点. 这就意味着,完全二叉树的高是[logN] 特点: 任意位置i: 左儿子在位置2i上,右儿子在位置2i+1上,父亲在i/2上 一个堆数据结构将由一个Comparable数组和一个代表当前堆的大小的整数组成: 优先队列的接口: 1 template <typename Comparable> 2 class BinaryHeap 3 { 4 public: 5 explicit BinaryHeap ( int capac

C#中基于数组的实现二叉堆

using System;using System.Collections;namespace DataStructure{ /// <summary> /// BinaryHeap 的摘要说明.-------二叉堆(基于数组的实现) /// </summary> public class BinaryHeap:IPriorityQueue { protected ArrayList array; //建立一个最多容纳_length个对象的空二叉堆 public BinaryHea

二项堆(一)之 图文解析 和 C语言的实现

概要 本章介绍二项堆,它和之前所讲的堆(二叉堆.左倾堆.斜堆)一样,也是用于实现优先队列的.和以往一样,本文会先对二项堆的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现:实现的语言虽不同,但是原理一样,选择其中之一进行了解即可.若文章有错误或不足的地方,请不吝指出! 目录1. 二项树的介绍2. 二项堆的介绍3. 二项堆的基本操作4. 二项堆的C实现(完整源码)5. 二项堆的C测试程序 转载请注明出处:http://www.cnblogs.com/skywan