Java算法之简单排序算法笔记记录

本篇主要记录冒泡排序,选择排序,插入排序。


冒泡排序

算法思想:
如下图,先比较0与1位置上的运动员身高,若0位置身高大于1位置身高,则0与1位置上的运动员交换位置,然后从1位置开始,比较1与2位置上运动员的身高,以此类推,直至到位置9。此时,9已经是最高的了,属于有序状态,所以下次比较的时候,只需要从0位置开始比较,直至位置8即可。


不变性:
我们发现,每次经过一轮比较后,总会有一个运动员的位置不再改变了,也就是说第一次比较,你得到的是0-9位置运动员中身高最高的,并且放置在位置9,第二次比较,注意咯,此时只需要比较0-8位置上的运动员身高,得到0-8最高运动员,并且放置在位置8上,以此类推,直至无法改变。

冒泡排序效率:
通过观察可以发现,0-9个运动员,第一次需要比较9次,第二次需要比较8次,第三次7次……直到最后一趟比较一次。对于10个数据项,就是9+8+7+6+5+4+3+2+1=45,对于N项来说,就是(N-1)+(N-2)+…+1=N*(N-1)/2,而交换的次数少于比较的次数,交换次数平均大约 N2/4 次。所以,冒泡排序运行需要 O(N2) 时间级别。
核心代码:

//arr代表的是需要排序的数组
public  void bubble(){
        for(int out=arr.length-1;out>1;out--){
            for(int inner=0;inner<out;inner++){
                if(arr[inner]>=arr[inner+1]){ //比较相邻位置数据的大小
                //满足条件则交换数据
                    int temp=0;
                    temp=arr[inner+1];
                    arr[inner+1]=arr[inner];
                    arr[inner]=temp;

                }
            }

        }

    }

选择排序

选择排序改进了冒泡排序,将必要的交换次数从 O(N2) 减少到 O(N)
算法思想:
进行选择排序就是把所有的队员扫描一遍,从中挑出最矮的一个运动员。最矮的运动员和站在队列最左端的队员交换位置,即站到0号位置,这是0号位置是最矮的,即下次排序并不需要参加,下次排序仅需要从1位置开始扫描。
选择排序前三次的示意图:


不变性:
每次排序后的最左端的n个数据总是有序的且位置不再改变
算法效率:
选择排序和冒泡排序执行了相同的比较次数,但是交换次数却大大减少
核心代码:

//选择排序
    public void select_sort(){
        int min; //记录最小数值的下标
        int i,j;
        for( i=0;i<arr.length-1;i++){
            min=i;
            for(j=i+1;j<arr.length;j++){
                if(arr[j]<arr[min])
                    min=j; //满足条件则将下标改变为j
            }
            //扫描一遍后交换位置,即最小的
            int temp;
            temp=arr[i];
            arr[i]=arr[min];
            arr[min]=temp;

        }

    }

插入排序

算法思想:
插入排序算法是一个对少量元素进行排序的有效算法。插入排序的工作原理与打牌时整理手中的牌的做法类似,开始摸牌时,我们的左手是空的,接着一次从桌上摸起一张牌,并将它插入到手的正确位置。为了找到这张牌的正确位置,要将它与手中已有的牌从右到左进行比较,无论什么时候手中的牌都是排序好的。

示意图:


当发现”被标记”队员大于左边某个运动员的身高时,这个”被标记”的运动员先出列,腾出位置,让那些运动员往后移,腾出一个位置给这个”被标记”的运动员入列。
不变性:
在每趟结束时,在将temp(“被标记”的运动员的信息)位置的项插入后,左侧的数据项是局部有序的
算法效率:
复制的次数大致等于比较的次数。然而,一次复制与一次交换的时间耗费不同,所以相对于随机数据,插入算法比冒泡排序快一倍,比选择排序略快。
在任意情况下,对于随机顺序的数据排序进行插入排序需要 O(N2) 的时间级。
如果数据基本有序,插入排序几乎只需要 O(N)
然而,对于逆序排序的数据,每次比较和移动都会执行,所以插入排序不比冒泡排序快。
核心代码:

//插入排序算法
public void insert_sort(){
    int in;
    for(in=1;in<arr.length;in++){//从位置1开始
           int temp=arr[in];                
           while(in>0&&arr[in-1]>=temp){ //位置in与位置in-1元素大小比较
            arr[in]=arr[in-1];    //满足条件,依次向右移动
            --in;
        }
        arr[in]=temp; //补位置,填坑

    }

}

几种简单排序之间的比较:

选择排序虽然把交换次数降到了最低,但比较的次数仍然很大。当数据量很小,并且交换数据相对于比较数据更加耗时的情况下,可以应用选择排序。
在大多数情况下,假设当数据量比较小或基本上有序时,插入排序算法是三种简单排序算法中最好的选择。对于更大数据量的排序来说,快速排序通常是最快的方法。

PS:不变性指在算法运行时保持不变的条件。

参考资料:Java数据结构和算法(第二版)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值