十大排序算法(二)选择、插入、希尔排序

2. 选择排序

***算法思想:***以从小到大排序为例,首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。

public static void selectSort(int[] arr){
    	int n = arr.length;
        //从无序区间中不断挑选出最小值,挑选n-1次,最后一个元素不用挑选
        for(int i = 0;i < n - 1;i++){
            int minIndex = i;

            for(int j = i + 1;j < n;j++){
                if(arr[j] < arr[minIndex]){
                    minIndex = j;  //更新最小值下标
                }
            }
            //交换最小值与无序区间第一个元素
            if(minIndex != i){
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
    }

此排序算法是不稳定的,解释见下面:
原始数据:3 5 3 2
i = 0时: 2 5 3 3
i = 1时:2 3 5 3
i = 2时:2 3 3 5
可以看到经过排序以后,原来加粗的3在前面,现在跑到后面去了,因此是不稳定的。

3. 插入排序

类似于玩扑克牌时,左手放置了若干已经排好顺序的牌,右手中是新摸的一张牌,因此需要将抽到的牌插入到当前手中牌的合适位置。

***算法思想:***将待排序序列分成两个序列,前面的序列保持有序(默认第一个元素是有序的),后面的序列保持无序。每次从无序序列中取出第一个元素,把该元素在已经排序的序列中从右往前扫描进行比较,然后插入到合适的位置,使之成为新的有序表。

public static void insertSort(int[] arr){
    	int n = arr.length;
        //i从第二个元素开始,默认第一个元素是有序的
        for(int i = 1;i < n;i++){
            int inserted = arr[i];  //待插入元素
            int index = i - 1;  //待插入元素前一个元素的索引
            while(index >= 0 && arr[index] > inserted){
                //每当前面的元素比待插入元素大,就向后移动
                arr[index + 1] = arr[index];
                index--;
            }
            //已经找到了待插入位置,即index+1
            arr[index + 1] = inserted;
        }
    }

此排序算法是稳定的。

4. 希尔排序

希尔排序可以说是插入排序的一种变种。由于插入排序每次只能交换两个相邻的元素,因此希尔排序加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序。

***算法思想:***希尔排序的思想是采用插入排序的方法,让数组中任意间隔为 h 的元素有序,刚开始 h 的大小可以是 h = n / 2,接着让 h = n / 4,让 h 一直缩小,当 h = 1 时,也就是此时数组中任意间隔为1的元素有序,此时的数组就是有序的了。

首先它把较大的数据集合分割成若干个小组(逻辑上分组),然后对每一个小组分别进行插入排序,此时,插入排序所作用的数据量比较小(每一个小组),插入的效率比较高。

public static void insertI(int[] arr,int i,int gap){
        int inserted = arr[i];
        int j = i - gap;
        while(j >= 0 && arr[j] > inserted){
            arr[j + gap] = arr[j];
            j = j - gap;
        }
        arr[j + gap] = inserted;
    }

    public static void shellSort(int[] arr){
        int n = arr.length;
        //进行分组,最开始的时候,gap为数组长度一半
        for(int gap = n / 2;gap > 0;gap /= 2){
            //对各个分组进行插入排序
            for(int i = gap;i < n;i++){
                //将arr[i]插入到所在分组正确的位置上
                insertI(arr,i,gap);
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值