首页 > 其他分享 >图解二叉堆(优先队列)TS实现

图解二叉堆(优先队列)TS实现

时间:2024-09-26 19:49:23浏览次数:10  
标签:node min TS 二叉 nodex heap 图解 节点 size

结构性:用数组表示的完全二叉树

堆序性:任意一个根节点比其所有子树节点大(小)

我们以数组作为存储结构,这样直接就可以明白,二叉堆需要的是完全二叉树即除了最后一层其他层都需要填满且最后一层的节点需要满足从左往右。

节点关系:

对于给定的节点i(假设数组索引从0开始):

  • 父节点的索引是 (i - 1) / 2(向下取整)。
  • 左节点的索引是 2 * i + 1
  • 右节点的索引是 2 * i + 2

重点思想

图解以大根堆为例子

增加元素

**时间复杂度**O(logN)

在底层最右侧添加节点,并不断与父节点进行比较,直到父节点比它小或者大于根节点。

上浮代码实现
swim(node:number){
  // 处于堆顶
    if(node == 0){
        return;
    }
  // 不断与父节点比较替换
    while(this.comp(this.heap[node], this.heap[this.parent(node)])){
        this.swap(node, this.parent(node));
        // 指针移动
        node = this.parent(node);
    }
}
往堆底添加元素

上浮操作

还原堆序性

刪除元素

**时间复杂度**O(logN)

移除最顶根节点,并把底层最右侧的节点移到堆顶,然后不断寻找子树最小节点交换,直到本身都小于子树。

下沉代码实现
private sink(node:number){
        // 传入参数不对
        if(node < 0){
            return;
        }
        // 边界
        while(this.left(node) < this.size() || this.right(node) < this.size()){
            let min_nodex = node;
            // 检测左子树
            if(this.left(node) < this.size() && this.comp(this.heap[this.left(node)], this.heap[min_nodex])){
                min_nodex = this.left(node);
            }
            // 检测右子树
            if(this.right(node) < this.size() && this.comp(this.heap[this.right(node)], this.heap[min_nodex])){
                min_nodex = this.right(node);
            }

            if(min_nodex == node){
                break;
            }
            // 与符合值交换
            this.swap(min_nodex, node);
            // 指针移动
            node = min_nodex;
        }
        
    }
弹出堆顶元素

将堆底元素移到堆顶

对堆顶元素进行 下沉 操作

还原堆序性

TS代码实现

注意此实现没有包括扩容缩容操作,读者需要的话可以自行实现。

class PriorityQueue<T>{
    private heap:T[];
    private _size:number;
  	private comp:(x:T, y:T)=>boolean;
    constructor(comp:(x:T, y:T)=>boolean){
        this.heap = [];
        this._size = 0;
    		this.comp = comp;
    }
    // 堆的大小
    public size(){
        return this._size;
    }
    // 判断堆是否为空
    public isEmpty(){
        return this._size === 0;
    }
    // 添加元素
    public push(val:T){
        this.heap.push(val);
        this._size++;
        this.swim(this.size() - 1);
    }
    // 弹出元素
    public pop():T{
        if(this.isEmpty()){
            throw new Error("PriorityQueue pop error, queue is empty");
        }
        let val = this.heap[0];
        // 将堆底节点移到堆顶
        this.heap[0] = this.heap[this._size-1];
        // 对原本在堆底的节点下沉操作
    		this.sink(0);
        this._size--;
        return val;
    }
    // 获得节点的父节点
    private parent(node:number){
        // 向下取整
        return Math.floor((node-1) / 2);
    }
    // 获得节点的左节点
    private left(node:number){
        return 2 * node + 1;
    }
    // 获得节点的右节点
    private right(node:number){
        return 2 * node + 2;
    }
    // 交换两个节点 
    private swap(i:number, j:number){
        [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]
    }
    // 上浮操作
    private swim(node:number){
        if(node == 0){
            return;
        }
        while(this.comp(this.heap[node], this.heap[this.parent(node)])){
            this.swap(node, this.parent(node));
            // 指针移动
            node = this.parent(node);
        }
    }
    // 下沉操作
    private sink(node:number){
        // 传入参数不对
        if(node < 0){
            return;
        }
        // 边界
        while(this.left(node) < this.size() || this.right(node) < this.size()){
            let min_nodex = node;
            // 检测左子树
            if(this.left(node) < this.size() && this.comp(this.heap[this.left(node)], this.heap[min_nodex])){
                min_nodex = this.left(node);
            }
            // 检测右子树
            if(this.right(node) < this.size() && this.comp(this.heap[this.right(node)], this.heap[min_nodex])){
                min_nodex = this.right(node);
            }

            if(min_nodex == node){
                break;
            }
            // 与符合值交换
            this.swap(min_nodex, node);
            // 指针移动
            node = min_nodex;
        }
        
    }
    


}

// 用法
let h = new PriorityQueue<number>((x,y)=>{return x>y});
h.push(10);
h.push(1);
h.push(2);
h.push(4);
h.push(5);
h.push(0);
h.push(2);
let s = h.size();
for (let i = 0; i < s; i++) {
    console.log(h.pop());
}

适应场景

优化A*寻路算法

在A*算法中,需要维护一个开放列表(open list),用于存储待处理的节点。二叉堆可以用来优化这个开放列表的管理。通过使用最小堆,可以快速地从开放列表中找到具有最低F值(即总成本最低的节点)的节点进行处理。

优先队列

比如说,可以通过设置优先级来判断加载的资源包,根据重要程度进行加载。亦或是UI弹窗等等,适用于需要设置优先级的功能。

标签:node,min,TS,二叉,nodex,heap,图解,节点,size
From: https://blog.csdn.net/2301_80175612/article/details/142574357

相关文章

  • C# Linq.FirstOrDefault、Linq.Where、Linq.AsParallel、List.Exists、List.Find、Dic
    C#Linq.FirstOrDefault、Linq.Where、Linq.AsParallel、List.Exists、List.Find、Dictionar.TryGetValue、HashSet.Contains性能的比较 今天我们来比较一下集合检索方法性能更优问题,测试代码publicclassEntity{publicintId{get;set;}publicintNo{......
  • 数据结构:实现链式结构二叉树(Tree) 手把手带你入门数据结构~
    文章目录前言一、链式结构二叉树的概念1.定义2.节点结构3.操作4.优势与劣势二、链式结构二叉树的实现1.树结构的定义2.树的遍历(1)前序遍历(2)中序遍历(3)后序遍历3.二叉树结点个数4.二叉树叶子结点个数5.二叉树第k层结点个数6.二叉树的深度/高度7.二叉树查找值为......
  • 1.1 HuggingFists简介(一)
    HuggingFists是一款低代码的AI应用开发及运营平台。有别于很多同类型的开发平台,其采用了传统数据科学平台的技术架构。因此,其不但可以帮助用户使用LLM在内的各类AI模型快速搭建出RAG(检索增强生成)、Agent(智能体)、知识图谱等应用;还可以帮助用户完成全结构(结构、半结构、非结......
  • Kotatsu 漫画阅读器v7.6自带800+漫画源
     Kotatsu漫画阅读器:开启漫画之旅当你沉浸于无尽的漫画世界时,选择一款适合自己的阅读软件尤为重要。而Kotatsu漫画阅读器就是为你精心打造的这款阅读工具。今天,让我们详细了解一下这款软件的魅力所在。一、软件概述Kotatsu漫画阅读器是一款功能强大且易于使用的漫画阅读平......
  • 平衡二叉搜索树
    PART0:引子二叉树想必大家都很熟悉,它在编程中具有很广泛的应用,而二叉树又分为很多种,这里介绍的了两种二叉树和一种他们的结合体。PART1:二叉搜索树二叉搜索树的定义二叉搜索树要求任意一个节点的左子节点小于它,右子节点大于它。如图在二叉搜索树上查找的时间复杂度相比线性......
  • COMM1190 Data, Insights and Decisions
    COMM1190 Data, Insightsand DecisionsAssessment 1:InitialreportTelcomCochurnrate projectThe General Manager (GM) at TelcomCo is mandated to deliver a customer retention update to the Board of Directors. To prepare, the GM in......
  • CSSE2310 Command Line Arguments
    CSSE2310–Semester2,2024Assignment3IntroductionThegoalofthisassignmentistodemonstrateyourskillsandabilityinfundamentalprocessmanagementandcommunicationconcepts(pipesandsignals),andtofurtherdevelopyourCprogrammingskills......
  • WPF canvas Draw line , ellipse and rectangle, save canvas and contents as pictu
    //xaml<Windowx:Class="WpfApp417.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mi......
  • [Python手撕]判断二叉搜索树
    #Definitionforabinarytreenode.#classTreeNode:#def__init__(self,val=0,left=None,right=None):#self.val=val#self.left=left#self.right=rightclassSolution:defisValidBST(self,root:Optional[TreeNod......
  • Camera ITS场景0_test_solid_color_test_pattern测试失败
    也会导致cts中CtsSensorPrivacyTestCases模块中两个单项报错,testOpStartsRunningAfterStartedWithSensoryPrivacyEnabledtestOpGetsRecordedAfterStartedWithSensorPrivacyEnabled这两项metadata加上MTK_SENSOR_TEST_PATTERN_MODE_OFF,MTK_SENSOR_TEST_PATTERN_MODE_BLACK就......