面试官问实现Top K 用什么方式,于是我拿出手Java Swing 实现了堆排序的演示过程。吊打面试官

64 阅读2分钟

面试官问实现Top K 用什么方式,于是我拿出手Java Swing 实现了堆排序的演示过程。吊打面试官

原创 今夜写代码 今夜写代码 2024-06-26 20:58 浙江

问题背景

图片

        关于标题中的Top K 问题,很适合用堆排序,因为堆排序每次建立堆,就知道了一个最值,无需将所有集合排完序,时间复杂度为 K log(N)。本想找个动画直观演示堆排序过程,发现没有,那就自己写一个吧。效果见上图,本文用到的技术

  • 完全二叉树
    • 父子节点下标关系
    • 元素个数与树高度关系
  • 堆排序实现过程
  • Swing
    • 自定义组件 paintComponent 

    • 刷新组件  repaint()

数组元素以二叉树展示实现

二叉树知识复习

1)完全二叉树数组下标i 的元素左孩子下标:2* i +1右孩子下标:2* i + 22)第 i 层 (i 从0开始) 最多有 2^i 个元素
如何保证画出来的二叉树对称,无重叠

      我的解决方法是先考虑满二叉树最后一层,将最后一层水平,按照固定间距放置,即最后一层 相邻之间节点 之间Δx 差值相同,y值相同。除了最后一层,其他层的元素位置由左右孩子决定的,即父节点 x 值取平均值,y 值减 Δx,效果图与伪代码如下

int left = 2 * i + 1;int right = 2 * i + 2;xValues[i] = (xValues[left] + xValues[right]) / 2;yValues[i] = yValues[left] - H_SPAN;

image.png 如果树不是满二叉树也不要紧,也按照满二叉树位置放置,多余的位置不显示而已。

Java Swing 绘制节点前面已经计算出每个节点的左边,文本可以用JLabel 实现,考虑要画个圈,我们extends JLabel 重写下paintComponent 画个圆

    protected void paintComponent(Graphics g) {        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();        g2d.setColor(Color.RED);        g2d.setStroke(new BasicStroke(3));        g2d.drawOval(00, WIDTH, HEIGHT);        g2d.dispose();    }

父子节点之间画线,就实现上面二叉树效果,接下来是排序中间状态记录

排序状态动画实现

定义三种状态,正常、比较中、交换

public enum BiNodeStatus {    NORMAL,    COMPARE,    SWAP;}

节点不同状态字体背景色不同,流程图如下图

switch (nodeStatus){    
case NORMAL:        
    setBackground(null);      
    setForeground(Color.BLACK);      
    break;    
case COMPARE:       
    setBackground(Color.RED);   
    break;
case SWAP:       
    setForeground(Color.BLUE);     
    break;    
default:      
    setBackground(null);  
    break;
}

694c0e8f27b1bb8a5edad31a4789b5c.png

image.png 最后完整代码已经上传,请多斧正,未来陆续实现其他排序