(Java)数据结构——排序(第一节)堆排序+PTA L2-012 关于堆的判断

前言

本博客是博主用于复习数据结构以及算法的博客,如果疏忽出现错误,还望各位指正。

堆排序(Heap Sort)概念

堆排序是一种基于堆数据结构的排序算法,其核心思想是将待排序的序列构建成一个最大堆(或最小堆),然后将堆顶元素与最后一个元素交换,再将剩余元素重新调整为最大堆(或最小堆),重复以上步骤直到所有元素都有序。

堆是一棵完全二叉树,因此一般可以当作数组处理。

对于最大堆,任何一个父节点的值都大于(或等于)其左右子节点的值;

对于最小堆,则是任何一个父节点的值都小于(或等于)其左右子节点的值。

建堆

上滤(插入新元素到堆中)

时间复杂度为O(N logN)

也就是一个一个插入,比如拿[46 23 26 24 10]来说,建堆过程就如下:

java 复制代码
        List<Integer> list = new ArrayList<>();
        String[] num = in.nextLine().split(" ");
        
        for(int i = 0;i<N;i++){
            //小顶堆的形成,自上而下建堆,一个一个插入
            if(list.size()==0){
                list.add(Integer.parseInt(num[i]));
            }else{
                //如果长度不是0,就插入后进行比较
                list.add(Integer.parseInt(num[i]));
                int count = i;
                while(count!=0){
                    int parent = 0;
                    if((count-1)%2==0){
                        parent = (count-1)/2;
                    }else if((count-2)%2==0){
                        parent =(count-2)/2;
                    }
                    if(list.get(count)<list.get(parent)){
                        int temp = list.get(count);
                        list.set(count,list.get(parent));
                        list.set(parent,temp);
                        count = parent;
                    }else{
                        break;
                    }
                }
            }
        }

下滤

一般用的是下滤,因为时间复杂度为O(N)

就是先整体插入,然后从倒数第一个非叶子结点进行堆调整:

1、找到倒数第一个非叶子结点23,判断其与子节点关系,发现比10大,于是互换

2、之后继续寻找非叶子结点,找到46,46与10交换后,继续与23交换

注意事项

建堆结束,两种方法建立的堆可能不一样,所以注意题目要求透露出的是哪一种。

比如要求上滤的:L2-012 关于堆的判断 - 团体程序设计天梯赛-练习集 (pintia.cn)

实现代码:

java 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] mn = in.nextLine().split(" ");
        int N = Integer.parseInt(mn[0]);
        int M = Integer.parseInt(mn[1]);
        List<Integer> list = new ArrayList<>();
        String[] num = in.nextLine().split(" ");

        for(int i = 0;i<N;i++){
            //小顶堆的形成
            if(list.size()==0){
                list.add(Integer.parseInt(num[i]));
            }else{
                //如果长度不是0,就进行比较
                list.add(Integer.parseInt(num[i]));
                int count = i;
                while(count!=0){
                    int parent = 0;
                    if((count-1)%2==0){
                        parent = (count-1)/2;
                    }else if((count-2)%2==0){
                        parent =(count-2)/2;
                    }
                    if(list.get(count)<list.get(parent)){
                        int temp = list.get(count);
                        list.set(count,list.get(parent));
                        list.set(parent,temp);
                        count = parent;
                    }else{
                        break;
                    }
                }
            }
        }

        //System.out.println(list.toString());
        //判断
        while(M-->0){
            String[] judge = in.nextLine().split(" ");
            //变成在数组中的下标
            int x = list.indexOf(Integer.parseInt(judge[0]));
            if(judge[3].equals("root")){
                if(x==0){
                    System.out.println("T");
                }else{
                    System.out.println("F");
                }
            }else if(judge[3].equals("are")){
                int y = list.indexOf(Integer.parseInt(judge[2]));
                if((y-1)%2==0){
                    if(y+1==x){
                        System.out.println("T");
                    }else{
                        System.out.println("F");
                    }
                }else if((y-2)%2==0){
                    if(y-1==x){
                        System.out.println("T");
                    }else{
                        System.out.println("F");
                    }
                }
            }else if(judge[3].equals("parent")){
                int y = list.indexOf(Integer.parseInt(judge[5]));
                if((y-1)%2==0){
                    if((y-1)/2==x){
                        System.out.println("T");
                    }else{
                        System.out.println("F");
                    }
                }else if((y-2)%2==0){
                    if((y-2)/2==x){
                        System.out.println("T");
                    }else{
                        System.out.println("F");
                    }
                }
            }else if(judge[3].equals("child")){
                int y = list.indexOf(Integer.parseInt(judge[5]));
                if((2*y+1) == x || (2*y+2)== x){
                    System.out.println("T");
                }else{
                    System.out.println("F");
                }
            }
        }
    }
}

当然,更简单的,可以直接使用Java提供的类,直接使用优先队列toArray解决:

【PTA-训练day1】L2-012 关于堆的判断 + L1-002打印沙漏_pta打印沙漏测试点-CSDN博客

Java优先队列

关于Java优先队列的一篇博主的博客详细介绍

【Java】PriorityQueue--优先级队列_java priorityqueue-CSDN博客

队列是一种先进先出(FIFO)的数据结构 ,但有些情况下, 操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列 ,该中场景下,使用队列显然不合适,比如:在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话.

在这种情况下, 数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。 这种数据结构就是 优先级队列(Priority Queue)。

JDK1.8 中的 PriorityQueue底层使用了堆这种数据结构 ,而堆实际就是在完全二叉树的基础上进行了一些调整。

默认情况下是小根堆,如果需要大根堆,则需要构建比较器。

其他方法与队列无异。

java 复制代码
PriorityQueue<Integer> q=new PriorityQueue<>(); //默认小顶堆
 
PriorityQueue<Integer> q=new PriorityQueue<>((a,b)->(b-a)); //大顶堆
 
q.contains(val);
 
Integer[] t=q.toArray(new Integer[n]); //将队列转化为数组

堆排序

上述三种建堆的方法,每次之后将最顶点进行一下处理(移除或者加入数组末尾等操作),然后重新建堆再操作即可实现堆排序。

应用场景

堆排序使用场景堆排序的使用场景与其他排序算法类似,适用于需要对大量数据进行排序的场景。比如取出第k大(小)的数,这时候可以用堆排序。

优/缺点

优点主要包括:

**时间复杂度较低:**堆排序的时间复杂度为 O(NlogN),相对于其他排序算法,其排序速度较快。

**不占用额外空间:**堆排序是一种原地排序算法,不需要额外的空间来存储排序结果。

**适用于大数据量的排序:**堆排序的时间复杂度不随数据量的增加而变化,因此适用于大数据量的排序。

缺点主要包括:

**不稳定性:**由于堆排序是通过交换元素来实现排序的,因此在排序过程中可能会破坏原有的相对顺序,导致排序结果不稳定。

**实现复杂:**相对于其他排序算法,堆排序的实现稍微复杂一些(不过借助Java提供的优先队列可以简单实现),需要理解堆数据结构的基本原理和实现过程。

代码(后续写了再上传,咕咕咕)

相关推荐
南宫萧幕15 分钟前
规则基 EMS 仿真实战:SOC 区间划分与 Simulink 闭环建模全解
算法·matlab·控制
爱滑雪的码农21 分钟前
Java基础十七:数据结构
数据结构
多加点辣也没关系31 分钟前
数据结构与算法|第二十三章:高级数据结构
数据结构·算法
庞轩px1 小时前
第七篇:Spring扩展点——如何优雅地介入Bean的创建流程
java·后端·spring·bean·aware·扩展点
孬甭_2 小时前
初识数据结构与算法
数据结构
tongluowan0073 小时前
一个请求在Spring MVC 中是怎么流转的
java·spring·mvc
hoiii1873 小时前
孤立森林 (Isolation Forest) 快速异常检测系统
算法
夜郎king3 小时前
Spring AI 对接大模型开发易错点总结与实战解决办法
java·人工智能·spring
oradh4 小时前
Oracle数据库中的Java概述
java·数据库·oracle·sql基础·oracle数据库java概述
组合缺一4 小时前
Java AI 框架三国杀:Solon AI vs Spring AI vs LangChain4j 深度对比
java·人工智能·spring·ai·langchain·llm·solon