zoukankan      html  css  js  c++  java
  • “深入理解”—选择排序算法



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


    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循环,第一个循环完成了将一个带排序序列构建成了一个大顶堆。第二个循环完成逐步将每个最大值的根节点与末尾元素交换,并且再次调整其为大顶堆。










  • 相关阅读:
    在Centos 7下编译openwrt+njit-client
    开博随笔
    Chapter 6. Statements
    Chapter 4. Arrays and Pointers
    Chapter 3. Library Types
    Chapter 2.  Variables and Basic Types
    关于stm32不常用的中断,如何添加, 比如timer10 timer11等
    keil 报错 expected an identifier
    案例分析 串口的地不要接到电源上 会烧掉
    案例分析 CAN OPEN 调试记录 进度
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6467306.html
Copyright © 2011-2022 走看看