三种基础排序(冒泡、选择、插入排序)

这是本人的第一篇博客,看了刘未鹏大神的《暗时间》,想想还是应该写点博客,虽然内容都是从比人那里学来的,但是用自己的话去再诠释一遍,可能会有意外的收获。

好了,废话就到这里了,下面开始用最简单的方式介绍这三种排序吧。


1、冒泡排序

冒泡排序的过程,就是将数组里面的元素不断向后冒,一趟下来,最大的冒到了最后。这样说也许很不生动形象,来举一个例子就明白了。

a[ ] = {1,4,2,6,2,4};我们打算把大的元素冒后数组后面去:

第一次:a[ ] = {1,4,2,6,2,4} 接下来a[0]与a[1]进行比较,1<4 所以我们从4开始冒泡(如果前面的数小于后面的数,那么接着从大的数开始冒泡

第二次:a[ ] = {1,4,2,6,2,4} 接下来a[1]与a[2]进行比较,4>2 所以交换位置后:a[ ] = {1,2,4,64,2,4} 

第三次:a[ ] = {1,2,4,6,2,4} 接下来a[2]与a[3]进行比较,4<6 所以不用交换位置:a[ ] = {1,2,4,6,2,4} 

第四次:a[ ] = {1,2,4,6,2,4} 接下来a[3]与a[4]进行比较,6>2 所以交换位置:a[ ] = {1,2,4,2,6,4

第四次:a[ ] = {1,2,4,2,6,4} 接下来a[4]与a[5]进行比较,6>4 所以交换位置:a[ ] = {1,2,4,2,4,6
这样,相当于遍历一次数组,就把最大的6冒到最后了。


接下来又从a[0]开始冒泡,

第二次遍历的结果:a[ ] = {1,2,2,4,4,6

第三次遍历结果:a[ ] = {1,2,2,4,4,6没有交换,说明已经排好序了。


我们来看看代码,以java语言为例:

public static void bubbleSort(int a[],int size){

        int temp;//用于交换的临时变量
        boolean change = false;//用来判断是否提前排好序
        //第一层循环 说明要进行size次
        for(int i =0;i<size;i++){
            // j<size-i 是说明不用每次都冒泡到最后一个位置
            // 冒泡到无序的最后就好   已经冒泡上去的都是有序的
            //如果size-i会指针越界  因为下面要进行a[j]与a[j+1]的比较
            for(int j=0;j<size-i-1;j++){
                if(a[j]>a[j+1]){
                    temp = a[j+1];
                    a[j+1] = a[j];
                    a[j] = temp;
                    change = true;
                }
            }
            if(!change){
                break;//没有交换数据  说明已经排好序了
            }
        }
    }

相信大家都很容易看懂这段代码,可以不设置change这个标记值。


2.选择排序

选择排序,顾名思义就是每次选择一个最小或者最大的数,选择n次后,就可以排好序了。

还是以a[ ] = {1,4,2,6,2,4};为例,我们每次选择最小的,然后把前面的与最小的交换位置。

第一次选择从a[0] 到a[5]:最小的数:1 下标为0 交换a[0]与a[0]的元素a[ ] = {1,4,2,6,2,4};

第二次选择从a[1] 到a[5]最小的数:2 下标为4 交换a[1]与a[4]的元素a[ ] = {1,2,2,6,4,4};

第三次选择从a[2] 到a[5]:最小的数:2 下标为2 交换a[2]与a[2]的元素 a[ ] = {1,2,2,6,4,4};

第四次选择从a[3] 到a[5]:最小的数:4 下标为5 交换a[3]与a[5]的元素 a[ ] = {1,2,2,4,4,6};

第五次选择从a[4] 到a[5]:最小的数:4 下标为4 交换a[4]与a[4]的元素 a[ ] = {1,2,2,4,4,6};

这样就排好序了,很简单吧。


来看看代码:
public static void selectSort(int a[] ,int size){

        int index; //保存最小数的下标
        int min;//保存最小的数

        for(int i=0;i<size-1;i++){
            min = a[i];//每次初始前面的第一个数为最小的
            index = i; //最小的下标
            //寻找最小的数据并且记录下来下标
            for(int j=i;j<size;j++){
                if(a[j]<=min){
                    min = a[j];
                    index = j;
                }
            }
            //交换数据
            a[index] = a[i];
            a[i] = min;
        }
    }

代码也很简单,相信初学者看起来并没有难度。

3、插入排序
插入排序比上面两个复杂一点。插入排序就像是抽扑克牌,给扑克牌排序。我们会 右手新起的扑克牌插入到 左手有序的扑克牌合适的位置,这个过程就是插入排序的基本思想了。
还有一个例子,插入排序就相当于生活中的插队,你要插入一个排好的队伍里面,由于空间不够,所以每个人要向后退后一个身位给你插入(如果他们乐意让你插队的话)。
还是这个例子a[ ] = {1,4,2,6,2,4}; 首先,我们把a[0]当做一个有序的(不用当做,因为它就是有序的)。
然后开始插入,首先,将a[1]即把4插入到前面的有序数组,我们要找一个合适的位置插入4,我们可以从4所在的位置向前比较,直到a[i]<=4为止,那么a[i+1]就是合适的位置了。
我们发现a[1]现在的位置就是合适的位置。所以不用变化。
a[ ] = {1,4,2,6,2,4};
接着我们将a[2]插入到前面,我们发现a[2]应该插入到a[1]的位置,把原来的a[1]向后移动。
a[ ] = {1,2,4,6,2,4};
然后把a[3]插入到前面有序的数组,发现位置不用变。
a[ ] = { 1,2,4 ,6,2,4};
然后把a[4]插入到前面有序的数组,发现位置应该变到a[2],然后把有序数组往后移动一个位置。
a[ ] = { 1,2,2,4, 6,4};
然后把a[5]插入到前面有序的数组,发现位置应该变到a[4], 然后把有序数组往后移动一个位置
a[ ] = { 1,2,2,4,4, 6};

也许你有一个疑问,该如何全部向后移动一个位置呢?

这个可以看看代码
 public static  void insertSort(int[]a ,int size){
        int temp ;//保存待插入的数
        int index ; //保存合适保存的位置
        for(int i=1;i<size;i++){
            temp = a[i];
            index = i;
            for(int j=i-1;j>=0;j--){
                if(a[j]<temp) break;           
			 }
            //把数据向后移动
            for(int j=i;j>index;j--){
                a[j] = a[j-1];
            }
            a[index] = temp;
        }
    }

这个是先找到合适的位置,然后开始移动数据,其实我们可以把这两步合起来。
public static  void insertSort(int[]a ,int size){
        int temp ;//保存待插入的数
        int index ; //保存合适保存的位置
        for(int i=1;i<size;i++){
            temp = a[i];
            index = i;
            for(int j=i-1;j>=0;j--){
                if(a[j]<temp) break; //之前一次循环已经找到了最佳位置

                index = j;
                a[j+1] = a[j];//向后移动数据
            }
            a[index] = temp;//把数据赋值到合适位置
        }
    }

不难发现,这三种基础排序算法都是嵌套的for循环,时间复杂度是O(n^2),在数据量较小的时候,是可以用这个几个排序的,平均情况下其中的插入排序较好。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值