天天看点

一步一步解析java排序算法--堆排序(最小堆)

首先明确什么是堆?

一个数组:

int[] unsort={12,24,35,40,50,66,70,56,55};

堆的表现形式(这是一个最小堆,根节点是最小的):

一步一步解析java排序算法--堆排序(最小堆)

用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。(这样就是给数组建好堆了)

下面进入堆排序的核心步骤:堆节点的移动

一步一步解析java排序算法--堆排序(最小堆)

这里需要对unsort[3]=12进行调整

一步一步解析java排序算法--堆排序(最小堆)

对unsort[3]的子节点unsort[7],unsort[8]进行比较,符合最小堆!

对unsort[1]=24进行调整

一步一步解析java排序算法--堆排序(最小堆)

跟左子节点进行调整

对unsort[0]=40进行调整

一步一步解析java排序算法--堆排序(最小堆)

比较左右子节点,12<35;

12<40进行调整,上移;

比较左右子节点,24<50;

24<40,上移;

55<56;55>40;至此调整结束,24所在索引位置替换成40;

最小堆的根节点值最小。

下面看代码:

//从i节点开始调整, i节点的子节点为 2*i+1, 2*i+2
        public static void MinHeapFixdown(int a[], int i, int n)  
        {  
            int j, temp;  

            temp = a[i]; //取出节点值,比较,替换 
            j =  * i + ;  //左子节点
            while (j < n)  
            {  
                if (j +  < n && a[j + ] < a[j]) //在左右子节点中找最小的  
                    j++;  

                if (a[j] >= temp)  //说明已经排好序
                    break;  

                a[i] = a[j];     //把较小的子结点往上移动,替换它的父结点  
                i = j;  
                j =  * i + ;  //继续往下遍历比较
            }  
            a[i] = temp; //调整结束 
        }    
           

有了堆的调整操作,建立堆,进行堆排序:

/**
         * 建立最小堆  
         * 对数组中的每个元素进行子节点调整,最小的向上移动
         * @param a 数组
         * @param n 数组长度
         */
        static void MakeMinHeap(int a[], int n)  
        {  
            //n/2-1可以定位到最后一个数组元素了,子节点分别为n-2,n-1
            for (int i = n /  - ; i >= ; i--)  
                MinHeapFixdown(a, i, n);  
        }  
        public static void MinheapsortTodescendarray(int a[], int n)  
        {  
            for (int i = n ; i >= ; i--)  
            {  
                MakeMinHeap(a,i);//从根节点调整定位最小值,调整过后a[0]最小 
                swap(a,i-,);//交换值,此时a[0]最小,进行下沉;下次遍历进行调整不会调整a[i-1]
            }  
        }  
           

此时得到的数组是递减的:

public static void main(String[] args) {
        int[] unsort={,,,,,,,,};
        MinheapsortTodescendarray(unsort, unsort.length);
        for (int i = ; i < unsort.length; i++) {
            System.out.print("  "+unsort[i]);
        }

    }
           

运行结果:

101 100 80 56 55 40 24 12 8