• 堆排序


    package com.cisco.www.test;

    import java.util.Arrays;

    /**
    * 将待排序序列构造成为一个大顶堆,此时整个序列的最大值就是堆顶的根节点。
    * 将其与堆尾元素进行交换,此时末尾的值就是最大值。然后对剩余n-1个元素重新构成一个堆
    * 这个时候会得到n个元素的最小值
    * 堆是一个完全二叉树:要么是一个满二叉树,非叶节点孩子都是全的,满二叉树属于完全二叉树
    * 一个节点左孩子下标是:2*i+1;右孩子下标是:2*i+2
    * 一个节点的父节点的坐标是:(i-1)/2
    * 从头至尾只有数组结构,没有树的结构
    * 大根堆:在一棵完全二叉树中,每棵子树的头部都是这棵树的最大值就是大根堆
    * 怎么把数组变成一个大根堆?建立大根堆?
    * 每一步都会形成0到i的大根堆
    */
    public class HeapSort {
    public static void heapSort(int[] arr){
    if(arr==null||arr.length<2){
    return;
    }
    //先插入堆,构造一个大顶堆
    for(int i = 0 ; i < arr.length ; i++ ){
    heapInsert(arr,i);//0-i
    }
    int heapSize = arr.length;
    //第一个元素和最后一个元素进行交换,开始堆排序
    swap(arr,0,--heapSize); //最后位置上的数和0位置上的数进行交换
    while (heapSize>0){
    heapify(arr,0,heapSize);
    swap(arr,0,--heapSize);
    }

    }
    //建立大根堆的过程,时间复杂度O(N^2)
    private static void heapInsert(int[] arr, int index) {
    //自己的位置和父位置进行比较,如果自己位置的值比父位置的值大,就来到父位置
    while (arr[index]>arr[(index-1)/2]){
    //如果自己位置的值比父位置的值大,就将自己位置上的值和父位置的值进行交换
    swap(arr,index,(index-1)/2);
    //然后将索引移到父位置,重新这个过程
    index=(index-1)/2;
    }
    }

    private static void swap(int[] arr, int i, int j) {
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
    }

    /**
    * 在0-heapsize-1的位置上已经形成了堆,再向右就认为是越界的
    * @param arr
    * @param index
    * @param heapSize
    */
    public static void heapify(int[] arr,int index , int heapSize){
    int left = index*2+1;
    while (left<heapSize){ //保证left不越界,如果越界了说明已经是叶结点了,停在那里就可以了
    /**
    * left+1<heapSize表示右孩子也不越界,并且右孩子的值比左孩子的值要大
    * 下面这段代码的意思是左右孩子哪个值大,哪个值就是我们largest值的位置
    */
    int largest = left+1<heapSize&&arr[left+1]>arr[left]?left+1:left;//左右孩子比较
    largest=arr[largest]>arr[index]?largest:index;//左右孩子节点中较大的那个和父节点进行比较
    //如果和较大孩子相比,较大值的是自己,那么就直接break,不用向下沉了
    if(largest==index){
    break;
    }
    //当largest!=index的时候
    swap(arr,largest,index); //当前的数和左右孩子较大的数进行交换
    index=largest; //自己变成了较大孩子的下标
    left=index*2+1; //left向下走,重复while循环
    }

    }
    //for test
    public static void main(String[] args){
    int testTime = 1000000;
    int size = 100;
    int value = 100;
    boolean succeed = true;
    for(int i = 0 ; i<testTime ; i++){
    int[] arr1 = generateRandomArray(size,value);
    int[] arr2 = copyArray(arr1);
    heapSort(arr1);
    comparator(arr2);
    if(!isEqual(arr1,arr2)){
    succeed=false;
    break;
    }
    }
    System.out.println(succeed?"Nice":"Fucking fucked!");
    int[] arr= generateRandomArray(size,value);
    printArray(arr);
    heapSort(arr);
    printArray(arr);
    }

    private static void printArray(int[] arr) {
    if(arr==null){
    return ;
    }
    for(int i= 0 ; i<arr.length;i++){
    System.out.print(arr[i]+" ");
    }
    System.out.println();
    }

    private static boolean isEqual(int[] arr1, int[] arr2) {
    if((arr1!=null&&arr2==null)||arr1==null&&arr2!=null){
    return false;
    }
    if(arr1==null&&arr2==null){
    return true;
    }
    if(arr1.length!=arr2.length){
    return false;
    }
    for(int i = 0 ; i<arr1.length;i++){
    if(arr1[i]!=arr2[i]){
    return false;
    }
    }
    return true;
    }

    private static void comparator(int[] arr) {
    Arrays.sort(arr);
    }

    //for test
    //随机产生一个0-100长度的随机数组
    private static int[] generateRandomArray(int size, int value) {
    //生成一个0到100的随机数组
    int[] arr = new int[(int)(Math.random()*(size+1))];
    for(int i = 0 ; i <arr.length;i++){
    arr[i] = (int)((value+1)*Math.random())-(int)(value*Math.random());
    }
    return arr;
    }
    //for test
    public static int[] copyArray(int[] arr){
    if(arr==null){
    return null;
    }
    int[] res = new int[arr.length];
    for(int i = 0 ; i <arr.length;i++){
    res[i] = arr[i];
    }
    return res;

    }
    }
  • 相关阅读:
    APICloud学习笔记之图片缓存
    正则表达式笔记01
    hahah
    panel 绑定鼠标滚轮事件
    C#无边框窗体移动 将事件绑定到想实现的控件上
    消消看最高分破解
    字符串补齐
    ant android打包--学习第一弹
    Windsock套接字I/O模型学习 --- 第三章
    Lua 垃圾收集机制
  • 原文地址:https://www.cnblogs.com/bigdata-stone/p/11043263.html
Copyright © 2020-2023  润新知