选择排序算法

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

 

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

 

 

[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
//选择排序
         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、堆排序:

 

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

 

大顶堆:每个节点的值都大于或等于其左右孩子节点的值

小顶堆:每个节点的值都小于或等于其左右孩子节点的值

 

堆排序算法的定义:

 

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

 

堆排序完整代码如下:

 

[Java] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class TestHeapSort {
     
    public static void main(String[] args){
         
        int[] arr={3,1,2,4,7,6,5,9,8,10};
        HSort(arr);
         
        for(int a:arr)
           System.out.print(a+" ");
    }
    // 堆排序
    //进行堆排序方法 
    private static void HSort(int[] arr){ 
        //1、构建大顶堆 
        for(int parent=(arr.length-1)/2;parent>=0;parent--){ 
            MaxHeap(arr,parent,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;  //循环结束 
    
}

 

在第一次构建大顶堆时,我们int parent = (arr.length-1)/2,也就是父节点从arr[4] = 7开始,4、3、2、1 、0都存在孩子节点。

 

官方一点就是:我们从最下层最右边的非终端节点开始构建,将其与其孩子节点进行比较和若有必要的互换,对于每个非终端节点来说,其实最多进行两次比较和互换操作,因此整个构建堆的时间复杂度为O(N)。

 

在正式排序时,第i 次取堆顶记录重建堆需要O(logi)的时间,(完全二叉树的某个节点到根节点的距离为logi+1),并且需要取n-1次堆顶记录,因此,重建堆的时间复杂度为O(nlogN)。

 

故,总体上堆排序的时间复杂度为O(nlogn)。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值