浅解前端必须掌握的算法(五):堆排序(上)

简介:

前言

虽然前端面试中很少会考到算法类的题目,但是你去比如像腾讯一样的大厂面试的时候就知道了,对基本算法的掌握对于从事计算机科学技术的我们来说,还是必不可少的,每天花上 10 分钟,轻松了解基本算法概念以及前端的实现方式。

另外,掌握了一些基本的算法实现,对于我们日常开发来说,也是如虎添翼,能让我们的 js 业务逻辑更趋高效和流畅。

特别说明

今天这个算法稍微比较复杂,牵扯到的概念也比较多,需要先了解基础知识。我给每篇文章的定位是 10 分钟内应该要掌握下来,所以我就擅作主张地将堆排序算法讲解分割为上、下两篇文章了,希望能让大家阅读起来更清爽愉快。

文章结构

《堆排序(上)》文章结构:

  • 简单的二叉树
  • 简单的满二叉树
  • 简单的完全二叉树
  • 简单的堆
  • 简单的堆分类

《堆排序(下)》文章结构:

  • 算法介绍
  • 轻松实现大顶堆调整
  • 轻松实现创建大顶堆
  • 轻松实现堆排序
  • 复杂度分析

简单的二叉树

要了解堆,必须先了解一下二叉树,两者关系在下一步阐述。

二叉树(Binary Tree)是每一个节点最多有两个分支的树结构,通常分支被称作「左子树」和「右子树」,分支具有左右次序,不能随意颠倒。

二叉树第 i 层最多拥有 2^(i-1) 个节点,深度为 k 的二叉树最多共有 2^(k+1)-1 个节点,且定义根节点所在的层级 i=0,所在的深度 k=0。注意该定义在全文起作用,后续不继续提及。

f8a3a5ffacfeb3560372c0bfee9c2ad601689237


简单的满二叉树

假设某个二叉树深度为 k,第 i 层拥有 2^(i-1) 个节点,且总共拥有 2^(k+1)-1 个节点,这样的二叉树称为「满二叉树」。

换句话说,二叉树的每一层都是满的,除了最后一层上的节点,每一个节点都具有左节点和右节点。

0f60fd7dfa78596298b0721e22a41a75d2100643

简单的完全二叉树

假设某个二叉树深度为 k,共有 n 个节点,当且仅当其中的每一个节点,都可以和同样深度为 k 的满二叉树上的,按层序编号相同的节点,也就是序号为 1n 的节点,均一一对应时,这样的二叉树称为「完全二叉树」。

满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树。

a6ab612342e9e554c1e03ed8ba23be59c6da1b9c


如下的就不是完全二叉树,树 1 中 10 号节点缺失,树 2 中 6、7 号节点缺失,树 3 中 10、11 号节点缺失。
f424c59d8ba1cb811ba0a357dd155ae25351fe07

简单的堆

堆(Heap),一类特殊的数据结构的统称,通常是一个可以被看做一棵树的数组对象。

堆的实现通过构造二叉堆(binary heap),实为二叉树的一种,由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。

堆,是完全二叉树。

79a8ae5fb1ea0890776671c99e4e32f992e2733c

对于给定的某个节点的下标 idx,可以很容易地计算出这个节点的父节点与孩子节点的下标:


// 计算父节点的下标
var getParentPos = function(idx){
  return Math.floor(idx / 2);
}

// 计算左子节点的下标
var getLeftChildPos = function(idx){
  return 2*idx;
};

// 计算右子节点的下标
var getRightChildPos = function(idx){
  return 2*idx + 1;
};

如下图,取下标 idx = 4 的节点,则其父节点的下标就为 Math.floor(4/2) === 2,其左子节点的下标就为 2*4 === 8,其右子节点的下标就为 2*4 + 1 === 9

2338fdb64ff51e4da2ada70a67e6de31c2e01d00

但将堆转换为数组时,由于数组的初始化下标始终为 0,所以我们的堆数据结构模型在此时要发生如下改变:

8e9b153a63d7a49380b8dd7448bf97a6433c7449

的,以上的算法也需要做一下微调:

// 计算父节点的下标
var getParentPos = function(idx){
  return Math.floor((idx-1) / 2);
}

// 计算左子节点的下标
var getLeftChildPos = function(idx){
  return 2*idx + 1;
};

// 计算右子节点的下标
var getRightChildPos = function(idx){
  return 2 * (idx+1);
};

简单的堆分类

二叉堆一般分为两种:「大顶堆」和「小顶堆」。

假设有一个堆,其中每个节点的值都大于或等于其左右孩子节点的值,则该堆称为「大顶堆」。「大顶堆」的最大元素值出现在根节点。

62e03f711c9a5badc8d29f3e7f423b0e8822af20
假设有一个堆,其中每个节点的值都 小于或等于 其左右孩子节点的值,则该堆称为「小顶堆」。「小顶堆」的最小元素值出现在根节点。
56897d4b864d50e984d6c4b96f0dc6ce3e412bf3


原文发布时间为:2018年06月29日
原文作者:程序猿何大叔
本文来源: 掘金     如需转载请联系原作者

相关文章
|
5月前
|
算法 Python
数据结构算法--4堆排序
堆排序过程概述:建立大根堆,将堆顶最大元素移出并替换为末尾元素,调整保持堆性质,重复此过程直至堆为空,实现排序。时间复杂度为O(nlogn)。Python中可用heapq模块进行堆操作。
|
3月前
|
搜索推荐 前端开发 数据可视化
【优秀python web毕设案例】基于协同过滤算法的酒店推荐系统,django框架+bootstrap前端+echarts可视化,有后台有爬虫
本文介绍了一个基于Django框架、协同过滤算法、ECharts数据可视化以及Bootstrap前端技术的酒店推荐系统,该系统通过用户行为分析和推荐算法优化,提供个性化的酒店推荐和直观的数据展示,以提升用户体验。
152 1
|
1月前
|
算法 搜索推荐
数据结构与算法学习十八:堆排序
这篇文章介绍了堆排序是一种通过构建堆数据结构来实现的高效排序算法,具有平均和最坏时间复杂度为O(nlogn)的特点。
70 0
数据结构与算法学习十八:堆排序
|
1月前
|
算法 搜索推荐
算法之堆排序
本文介绍了堆排序算法的原理和实现,通过构建最大堆或最小堆,利用堆的性质进行高效的排序,并提供了具体的编程实现细节和示例。
20 0
算法之堆排序
|
1月前
|
算法 Java Go
深入了解堆排序算法
深入了解堆排序算法
22 1
|
30天前
|
移动开发 算法 前端开发
前端常用算法全解:特征梳理、复杂度比较、分类解读与示例展示
前端常用算法全解:特征梳理、复杂度比较、分类解读与示例展示
21 0
|
2月前
|
算法 前端开发 机器人
一文了解分而治之和动态规则算法在前端中的应用
该文章详细介绍了分而治之策略和动态规划算法在前端开发中的应用,并通过具体的例子和LeetCode题目解析来说明这两种算法的特点及使用场景。
一文了解分而治之和动态规则算法在前端中的应用
|
6月前
|
前端开发 算法
sass 公用10个mixins代码块,算法太TM重要了,前端开发要求
sass 公用10个mixins代码块,算法太TM重要了,前端开发要求
|
3月前
|
搜索推荐 前端开发 算法
基于用户画像及协同过滤算法的音乐推荐系统,采用Django框架、bootstrap前端,MySQL数据库
本文介绍了一个基于用户画像和协同过滤算法的音乐推荐系统,使用Django框架、Bootstrap前端和MySQL数据库构建,旨在为用户提供个性化的音乐推荐服务,提高推荐准确性和用户满意度。
252 7
基于用户画像及协同过滤算法的音乐推荐系统,采用Django框架、bootstrap前端,MySQL数据库
|
2月前
|
算法 前端开发
一文了解贪心算法和回溯算法在前端中的应用
该文章深入讲解了贪心算法与回溯算法的原理及其在前端开发中的具体应用,并通过分析LeetCode题目来展示这两种算法的解题思路与实现方法。