堆排序

最近心情烦躁的不行写不出来东西!哎

import java.io.BufferedInputStream;
import java.util.Scanner;
/**
 * 
 * @类描述:堆  && 实现堆排序
 * @项目名称:Aha_suanfa
 * @类名称:Dui
 * @修改备注:
 * @version v1.0
 * @Copyright go3c
 */
public class Dui {
    static int[] h = new int[101];
    static int n;

    public static void main(String args[]) {
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        n = sc.nextInt();
        int num = n;
        for (int i = 1; i <= n; i++) {
            h[i] = sc.nextInt();
        }
        create();
        System.out.println();
        for (int i = 1; i <= num; i++) {
            System.out.print(deleteMax() + "   ");
        }
    }

    public static void create() //建立 堆,按数组从头到尾 依次放入堆中,然后进行调整,这里用一维数组存储堆
    {
        for (int i = n/2; i >= 1; i--) {
            siftdown(i);
        }
    }

    public static int deleteMax() {
        int t;
        t = h[1];
        h[1] = h[n];
        n--;
        siftdown(1);
        return t;

    }

    private static void siftdown(int i) {
        // TODO Auto-generated method stub
        int t, flag = 0;
        while (i * 2 <= n && flag == 0) {
            if (h[i] > h[i * 2])// 取小·:先考虑左边的孩子
                t = i * 2;
            else
                t = i;

            if (i * 2 + 1 <= n) {// 取小,考虑右边的孩子。左右之间取最小的
                if (h[t] > h[i * 2 + 1]) {
                    t = i * 2 + 1;
                }
            }
            if (t != i) {
                swap(t, i);
                i = t;
            } else {
                flag = 1;
            }
        }

    }

    private static void swap(int x, int y) 
    {
        // TODO Auto-generated method stub
        int t;
        t = h[x];
        h[x] = h[y];
        h[y] = t;
    }
}

swap函数是交换函数!

把n个元素建立一个堆,首先可以将这n个结点以自顶点向下,从左到右的方式从1到n进行编号,这样就可以把n个结点转换为一棵完全二叉树,紧接着从最后一个非叶节点开始到根节点,(这里用到了二叉树的性质最后一个非叶节点的位置怎么求,在一棵树中能做父节点的结点有n/2个),开始从后往前扫描,根节点为1,做个扫描所有的节点,根据需要向下调整,直到以当前结点为根的节点的子树符合堆的特性:

核心代码只有两行:

for (int i = n/2; i >= 1; i--) {
            siftdown(i);
        }

在这里我顺便实现了堆排序!其实还是可以优化的的这个代码!哈哈!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值