• “深入理解”—选择排序算法




    选择排序算法有两种:直接选择排序和堆排序


    1、直接选择排序(Straight Select Sort)算法思想:第一趟从n个元素的数据序列中选出关键字最小/大的元素并放在最前/后位置,下一趟从n-1个元素中选出最小/大的元素并放在最前/后位置。以此类推,经过n-1趟完成排序。


    示例如下:

    	//选择排序
    	public static void selectsort(int[] a)
    	{
    		int temp;
    		for(int i=0;i<a.length;i++)
    		{
    			//内层循环j=i+1,外层循环控制着循环次数。即每趟中a[i]这个值就是本趟的最小值。i位置上是最小值
    			for(int j=i+1;j<a.length;j++)   
    			{
    				if(a[i]>a[j])
    				{
    					temp=a[i];
    					a[i]=a[j];
    					a[j]=temp;
    				}
    			}
    		}
    	}




    2、堆排序:


    堆排序涉及到完全二叉树的概念。堆是一个完全二叉树,分为大顶堆和小顶堆两种。

    大顶堆:每个节点的值都大于或等于其左右孩子节点的值。如图(1)所示:

    小顶堆:每个节点的值都大于或等于其左右孩子节点的值。如图(2)所示:

                            


                                            图 (1) 大顶堆                                                                                                          图( 2) 小顶堆



    堆排序算法的定义:

            堆排序(Heap Sort)就是利用堆(假设为大顶堆)进行排序的方法。其基本思想是:将待排序的序列构造成一个大顶堆,此时整个序列的最大值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余的 N -1个元素重新构造成一个堆,这样就会得到N个元素中的次小值。如此反复执行,最后将得到一个有序序列。


           以上图中的大顶堆为例,将根节点90与末尾元素20交换,如下图1,2所示:

    此时90成为了末尾元素,根节点元素成为了20。将20经过调整,使得除了90以外的所有节点继续满足大顶堆的定义,如图3,然后考虑将30和80互换。

                   





    堆排序完整代码如下:

    public class TestHeapSort {
    	
    	public static void main(String[] args){
    		
    		int[] arr={50,10,90,30,70,40,80,60,20};
    		HSort(arr);
    		
    		for(int a:arr)
    			System.out.println(a);
    	}
    	
    	//进行堆排序方法
    	private static void HSort(int[] arr){
    		
    		//1、构建大顶堆
    		for(int parent=(arr.length-1)/2;parent>0;parent--){
    			
    			MaxHeap(arr,parent-1,arr.length-1);
    		}
    		
    		for(int t=arr.length-1;t>0;t--){
    			
    			swap(arr,0,t); //交换数据
    			
    			MaxHeap(arr, 0, t-1);   //根节点从0开始,继续构建大顶堆。
    		}
    		
    		
    		
    	}
        
    	//交换数据方法
    	private static void swap(int[] arr, int i, int t) {
    		
    		int temp=arr[i];
    		arr[i]=arr[t];
    		arr[t]=temp;
    		
    	}
    
    	/*
    	 * 构建大顶堆的方法
    	 * s 代表拥有左右孩子节点的节点,即本次要调整位置的节点
    	 * m 代表当前堆的长度
    	 */
    	private static void MaxHeap(int[] arr, int s, int m) {
    	
    		int temp,j;
    		temp=arr[s];
    		
    		for(j=2*s+1;j<=m;j=2*j+1){   //j=2*s+1为s节点的左孩子,j+1为s节点的右孩子
    								     //j=2*j+1是要找到j的孩子节点
    			
    			if(j<m&&arr[j]<arr[j+1])
    				j++;     //将j指向当前左右孩子节点中的较大值
    			if(temp>arr[j])
    				break;  //如果s节点的值大于其最大的孩子节点值,则,循环结束,本次不做任何改变
    			
    			arr[s]=arr[j];  //否则将较大的孩子节点的值赋值给父节点
    			s=j;    //将j的值赋值给s,即j成为了下一波的父节点,继续比较
    			
    		}
    		arr[s]=temp;  //循环结束
    				
    	}
    
    }

    从代码中可以看出:

          排序过程分为两个for循环,第一个循环完成了将一个带排序序列构建成了一个大顶堆。第二个循环完成逐步将每个最大值的根节点与末尾元素交换,并且再次调整其为大顶堆。










  • 相关阅读:
    学习zabbix(一)
    学习openstack(七)
    并不对劲的bzoj3677:p3647:[APIO2014]连珠线
    并不对劲的bzoj5415:loj2718:uoj393:p4768:[NOI2018]归程
    并不对劲的bzoj5475:loj2983:p5206:[wc2019]数树
    并不对劲的多项式求ln,exp
    并不对劲的bzoj1758:p4292:[WC2010]重建计划
    (中等) UESTC 94 Bracket Sequence,线段树+括号。
    (简单) HDU 5154 Harry and Magical Computer,图论。
    (中等) UESTC 360 Another LCIS ,线段树+区间更新。
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6467306.html
Copyright © 2020-2023  润新知