手写大根堆

简介: 手写大根堆

用数组实现一个大根堆

实现功能

   每给一个数加进数组后,自动调整为大根堆结构(heapInsert()方法)

   返回大根堆中的最大值,并且在大根堆中把最大值删除,且剩下的数,依然保持为大根堆结构(heapify()方法)

自己手写一个大根堆结构 VS 纯暴力的方法,用对数器测试100万组!!!

package com.harrison.class04;
public class Code01_MaxHeap {
  public static class MyMaxHeap {
    private int[] heap;
    private final int limit;
    private int heapSize;
    public MyMaxHeap(int limit) {
      heap = new int[limit];
      heapSize = 0;
      this.limit = limit;
    }
    public void push(int value) {
      if (heapSize == limit) {
        throw new RuntimeException("heap is full");
      }
      heap[heapSize] = value;
      heapInsert(heap, heapSize++);
    }
    // 堆结构的两个关键操作:从某个位置开始往上看
    // 动态地建立大根堆
    // 如果收了N个数,时间复杂度为logN
    public static void heapInsert(int[] arr, int index) {
      while (arr[index] > arr[(index - 1) / 2]) {
        swap(arr, index, (index - 1) / 2);
        index = (index - 1) / 2;
      }
    }
    // 返回最大值,并在大根堆中把最大值删掉
    // 剩下的数,依然保持大根堆组织
    public int pop() {
      int ans = heap[0];
      swap(heap, 0, --heapSize);
      heapify(heap, 0, heapSize);
      return ans;
    }
    // 堆结构的两个关键操作:从某个位置开始往下调,时间复杂度logN
    // heapSize 自己想象范围的大小,并不是数组的实际大小!!!
    public static void heapify(int[] arr, int index, int heapSize) {
      int left=(2*index)+1;
      while(left<heapSize) {
        int largest=(left+1<heapSize && arr[left+1]>arr[left])?left+1:left;
        int allLargest=arr[largest]>arr[index]?largest:index;
        if(allLargest==index) {
          break;
        }
        swap(arr, allLargest, index);
        index=allLargest;
        left=(2*index)+1;
      }
    }
    public boolean isEmpty() {
      return heapSize==0;
    }
    public boolean isFull() {
      return heapSize==limit;
    }
  }
  public static void swap(int[] arr, int i, int j) {
    int t = arr[i];
    arr[i] = arr[j];
    arr[j] = t;
  }
  public static class RightMaxHeap{
    private int[] arr;
    private int size;
    private final int limit;
    public RightMaxHeap(int limit) {
      this.limit=limit;
      arr=new int[limit];
      size=0;
    }
    public void push(int value) {
      if(size==limit) {
        throw new RuntimeException("heap is full");
      }
      arr[size++]=value;
    }
    public int pop() {
      int maxIndex=0;
      for(int i=1; i<size; i++) {
        if(arr[maxIndex]<arr[i]) {
          maxIndex=i;
        }
      }
      int ans=arr[maxIndex];
      arr[maxIndex]=arr[--size];
      return ans;
    }
    public boolean isEmpty() {
      return size==0;
    }
    public boolean isFull() {
      return size==limit;
    }
  }
  public static void main(String[] args) {
    int testTimes=1000000;
    int limit=1000;
    int value=100;
    System.out.println("test begin");
    for(int i=0; i<testTimes; i++) {
      // [1,1000],防止出现零,否则一开始堆的大小就为0
      int curLimit=(int)(Math.random()*limit)+1;
      MyMaxHeap my=new MyMaxHeap(curLimit);
      RightMaxHeap test=new RightMaxHeap(curLimit);
      int curOopsTimes=(int)(Math.random()*limit);
      for(int j=0; j<curOopsTimes; j++) {
        if(my.isEmpty()!=test.isEmpty()) {
          System.out.println("Oops");
        }
        if(my.isFull()!=test.isFull()) {
          System.out.println("Oops");
        }
        if(my.isEmpty()) {
          int curValue=(int)(Math.random()*(value+1));
          my.push(curValue);
          test.push(curValue);
        }else if(my.isFull()) {
          if(my.pop()!=test.pop()) {
            System.out.println("Oops");
          }
        }else {
          if(Math.random()<0.5) {
            int curValue=(int)(Math.random()*(value+1));
            my.push(curValue);
            test.push(curValue);
          }else {
            if(my.pop()!=test.pop()) {
              System.out.println("Oops");
            }
          }
        }
      }
    }
    System.out.println("finish");
  }
}

相关文章
|
网络协议 网络架构
【计算机网络】OSI、TCP/IP、五层模型
【计算机网络】OSI、TCP/IP、五层模型
|
存储 缓存 安全
ConcurrentHashMap的实现原理,非常详细,一文吃透!
本文详细解析了ConcurrentHashMap的实现原理,深入探讨了分段锁、CAS操作和红黑树等关键技术,帮助全面理解ConcurrentHashMap的并发机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
ConcurrentHashMap的实现原理,非常详细,一文吃透!
|
存储 缓存 NoSQL
Redis 漫谈 —— 分布式布隆过滤及内存使用问题分析
Redis 分布式布隆过滤及内存使用问题分析
1331 0
Redis 漫谈 —— 分布式布隆过滤及内存使用问题分析
|
6月前
|
人工智能 算法 NoSQL
LRU算法的Java实现
LRU(Least Recently Used)算法用于淘汰最近最少使用的数据,常应用于内存管理策略中。在Redis中,通过`maxmemory-policy`配置实现不同淘汰策略,如`allkeys-lru`和`volatile-lru`等,采用采样方式近似LRU以优化性能。Java中可通过`LinkedHashMap`轻松实现LRUCache,利用其`accessOrder`特性和`removeEldestEntry`方法完成缓存淘汰逻辑,代码简洁高效。
286 0
|
9月前
|
存储 Java
几种锁:偏向锁、轻量级锁、重量级锁、自旋锁
**锁机制简介:** Java中,锁分为偏向锁、轻量级锁和重量级锁。偏向锁适用于单一线程多次获取同一锁的情况,减少无竞争下的性能消耗;轻量级锁在多线程竞争时通过自旋避免阻塞,提升效率;重量级锁则是在自旋超时或多个线程竞争时,将其他线程阻塞以防止CPU空转,但性能较低。锁的升级路径为:偏向锁 → 轻量级锁 → 重量级锁,且不可降级。偏向锁默认开启,可通过JVM参数调整或关闭。
367 18
|
关系型数据库 MySQL Java
spi机制打破双亲委派机制
在JDBC4及以上版本,连接MySQL数据库不再需要显式加载驱动(`Class.forName`),而是利用SPI机制。系统通过扫描`META-INF/services/java.sql.Driver`文件找到`com.mysql.cj.jdbc.Driver`并使用`ServiceLoader`由AppClassLoader加载。`DriverManager`在启动时加载所有可用的`Driver`实现,实现解耦和动态发现。虽然看起来逆向了双亲委派,但实际上每个类仍由适当的类加载器加载,保持了加载层次。
spi机制打破双亲委派机制
|
搜索推荐 算法 Java
堆排序实战:轻松实现高效排序,附详细Java代码
嗨,大家好!我是小米,一名热爱技术分享的程序员。今天要带大家了解堆排序——一种基于二叉堆的数据结构,具有O(n log n)时间复杂度的选择排序算法。堆排序分为构建大顶堆和排序两个阶段:先建堆使根节点为最大值,再通过交换根节点与末尾节点并调整堆来逐步排序。它稳定高效,空间复杂度仅O(1),适合对稳定性要求高的场合。虽然不如快速排序快,但在避免递归和节省空间方面有优势。一起动手实现吧!如果有任何疑问,欢迎留言交流!
339 2
|
运维 监控 定位技术
故障转移和自动恢复
故障转移和自动恢复
484 1
Java- IO 及其相关面试题(上)
Java- IO 及其相关面试题(上)
458 0
|
数据采集 存储 供应链
数据对账的目的是什么?
数据对账的目的是什么?
606 2