超详解内部排序算法之(一)冒泡排序

超详解常见的八种内部排序算法 -(一)冒泡排序

简单介绍

开篇

这是一篇小白开始接手写简单算法的小白文。写这边文章的主旨就是看到有小伙伴觉得算法一定会很难,纵观已有的文章,大多都是将整个处理代码帖出来的,让很多初次接触的小伙伴觉得不是很好理解。所以写这篇文章就是通过简单的示例+从特殊到一般的推导过程,帮助初次想要了解的小伙伴更好的理解算法。旨在消除小伙伴对于算法这一名词的莫名恐惧。
先简单说一下内部排序的算法类型


常见的内部排序算法

内部排序就是计算机内存中进行计算处理的算法,我们常见的内部排序算法为8种,其中可以按照不同的类型进行一些简单的分类,方便我们更好的理解,也比较容易建立我们的认知体系【金字塔原理】
术语解释

  1. 稳定 :如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
  2. 不稳定 :如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
  3. 时间复杂度 : 一个算法执行所耗费的时间。
  4. 空间复杂度 :运行完一个程序所需内存的大小,在现在都可以利用空间换取时间,空间复杂度不是我们考虑的首要选择。
    ——————————排序算法的归纳———————————
    在这里插入图片描述

写在最开始的话
说明,所有的实现代码是用Java进行编写实现的,但是内部的思想是公用的


我们直接进入正题:

一 、冒泡排序

冒泡排序的思路分析
第一步 了解冒泡排序的思路
冒泡排序的思路是对于列表中的元素,两两之间进行比较,从左到右依次开始比较,上图来让理解更清晰一些:
约定默认顺序是从小到大
在这先给出最后的结论性代码,有不明白的小伙伴可以继续往下看推导过程,可以更好的理解冒泡排序。

结论代码

public static void bubbleSort(int[] arr){
        //default sort is desc
        // we known inner process is for i in arr[] length-1 ,any process a max recursion reduce 1
        for (int i = 0; i < arr.length-1; i++) {
            for (int j = 0; j < arr.length-1-i; j++) {
                if(arr[j]>arr[j+1]){
                    int temp = arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
            //打印每一次的循环内的结果
            System.out.printf("The %d sorted result is \n",i);
            System.out.println(Arrays.toString(arr));
            }
        }
        //输出最终的结果
        System.out.println("The last sort is "+ Arrays.toString(arr));

    }

我们给定我们需要进行排序的一维数组:
[12, 4, 9, 112, -6, 5]
当我们拿到这样的数组的时候,我们先确定我们的策略,我们知道冒泡是两两之间进行比较,然后将较大的数放置在索引值较大的位置。就像气泡总是接近水面的泡泡体形是越大的,冒泡排序就很形象了。
第一轮循环

① 我们先进行第一次循环,我们从左到右,依次进行,第一次我们拿第一个元素12和第二个元素4 进行比较, 12 > 4 12>4 12>4 ,我们将12 和 4互换位置,得到结果 [ 4 , 12 , 9 , 112 , − 6 , 5 ] [4, 12, 9, 112, -6, 5] [4,12,9,112,6,5]

② 接着我们拿第二个元素12和第三个元素 9 进行比较, 12 > 9 12>9 12>9 ,将较大的数调整到后边的位置,得到结果:[4, 9, 12, 112, -6, 5]继续下一轮;

③ 我们拿第三个元素12和第四个元素112 进行比较, 12 < 112 12<112 12<112 ,不用做位置的调整,得到结果:[4, 9, 12, 112, -6, 5],继续下一轮;

④ 我们拿第四个元素112和第五个元素 -6 进行比较, 112 > − 6 112>-6 112>6 ,我们将较大的数放置在索引值大的位置,得到结果:得到结果:[4, 9, 12, -6, 112, 5]继续下一轮;

⑤我们拿第五个元素112和第六个元素5 进行比较,112>5 ,我们将较大的数放置在索引值大的位置,得到结果:得到结果:[4, 9, 12, -6, 5, 112]第一轮结束,我们就找到了第一个最大值。

第一轮循环我们一共花费了5次比较确定了第一个最大数,并将它放置在队列的最后一个位置。

在这里插入图片描述
第二轮循环

① 我们继续进行,第一次我们拿第一个元素4和第二个元素9 进行比较,4<9,我们不需要进行位置处理,得到结果[4, 9, 12, -6, 5, 112]

② 接着我们拿第二个元素 9 和第三个元素12 进行比较,我们不需要进行位置处理,得到结果:[4, 9, 12, -6, 5, 112]继续下一轮

③ 我们拿第三个元素12和第四个元素 -6 进行比较, 12 > − 6 12>-6 12>6,我们交换两数的位置,得到结果:[4, 9, -6,12, 5, 112],继续下一轮

④ 我们拿第四个元素12和第五个元素5 进行比较, 12 > 5 12>5 12>5 ,我们将较大的数放置在索引值大的位置,得到结果:得到结果:[4, 9, -6, 5, 12, 112],我们在此就不用比较最后一个元素了,因为第一轮我们已经确认了最后一个元素就是最大的元素;我们确定了第二大的数字及其位置。

第二轮我们走了4步完成
我们上图更好的理解一下

在这里插入图片描述

第三轮循环

① 我们继续进行,第一次我们拿第一个元素4和第二个元素9 进行比较, 4 < 9 4<9 4<9,我们不需要进行位置处理,得到结果[4, 9, -6, 5, 12, 112]

② 接着我们拿第二个元素9和第三个元素**-6** 进行比较, 9 > − 6 9>-6 9>6,我们交换两个数的位置,得到结果:[4, -6,9, 5, 12, 112]继续下一轮

③ 我们拿第三个元素9和第四个元素5 进行比较, 9 > 5 9>5 9>5,我们交换两个数的位置,得到结果:[4, -6, 5, 9, 12, 112],我们就得到了第三大个数值。

我们在这次循环中花费了3步处理

在这里插入图片描述
第四轮循环

① 我们继续进行,第一次我们拿第一个元素4和第二个元素 -6 进行比较, 4 > − 6 4>-6 4>6,我们需要进行位置处理,将两个数交换位置,得到结果[ -6,4, 5, 9, 12, 112]

② 接着我们拿第二个元素4和第三个元素 5 进行比较, 4 < 5 4<5 4<5,我们不用处理两个数的位置,得到结果:[ -6,4, 5, 9, 12, 112],我们确定了第四大的数字,

我们在当次循环中进行了2次比较操作;

在这里插入图片描述
第五轮循环

① 我们继续进行,第一次我们拿第一个元素 -6 和第二个元素4 进行比较, − 6 < 4 -6<4 6<4,我们不需要进行位置处理,得到结果[-6,4, 5, 9, 12, 112]

我们在当次循环中进行了1次比较操作;确定了第五大的数字,并将其放置在第2位,第一位是不是就是我们最小的数据和她的位置,就不需要在进行比较了,至此是不是排序都结束了。

在这里插入图片描述

1.我们进行排列的列表有6个元素,我们进行了5次循环,我们进行了n-1次的大循环
2.每次循环的内部操作的步骤是逐步减少的

第二步,代码推导实现

public static void bubbleSort(int[] arr){
       

        // 第一轮循环
        // i 的取值范围是从0-4,因为我们是拿当前和后一个比较的,当我们获取索引为4(第五个元素),我们可以拿到最后一个和当前元素比较的元素了
        for (int i = 0; i < arr.length-1; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i]=arr[i+1];
                arr[i+1]=temp;
            }
        }
		System.out.println("第一次循环的结果 \n");
		System.out.println(Arrays.toString(arr));

	      // 第二轮循环
		//我们第二轮值遍历前5个元素,最后一个元素已经确定不再参与比较,所以我们的i<arr.length-1-1
        for (int i = 0; i < arr.length-1-1; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i]=arr[i+1];
                arr[i+1]=temp;
            }
        }
		System.out.println("第二次循环的结果 \n");
		System.out.println(Arrays.toString(arr));

		// 第三轮循环
		//我们第三轮值遍历前4个元素,最后2个元素已经确定不再参与比较,所以我们的i<arr.length-1-1-1
        for (int i = 0; i < arr.length-1-2; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i]=arr[i+1];
                arr[i+1]=temp;
            }
        }
		System.out.println("第三次循环的结果 \n");
		System.out.println(Arrays.toString(arr));
		
		// 第四轮循环
		//我们第四轮值遍历前3个元素,最后3个元素已经确定不再参与比较,所以我们的i<arr.length-1-1-1-1
        for (int i = 0; i < arr.length-1-3; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i]=arr[i+1];
                arr[i+1]=temp;
            }
        }
		System.out.println("第四次循环的结果 \n");
		System.out.println(Arrays.toString(arr));
		
		// 第五轮循环
		//我们第五轮值遍历前2个元素,最后4个元素已经确定不再参与比较,所以我们的i<arr.length-1-1-1-1
        for (int i = 0; i < arr.length-1-4; i++) {
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i]=arr[i+1];
                arr[i+1]=temp;
            }
        }
		System.out.println("第五次循环的结果 \n");
		System.out.println(Arrays.toString(arr));

		//通过上边的代码我们可以总结出一个规律,就是对需要排列的列表有6个元素,我们进行了5次循环,我们进行了n-1次的大循环
		/**每次循环的内部操作的步骤是逐步减少的,且减少的数我们来看下,
		*第一次,arr.length-1-0
		*第二次,arr.length-1-1
		*第三次,arr.length-1-2
		*第四次,arr.length-1-3
		*第五次,arr.length-1-4
		*那我们用for循环做五次大循环,循环次数为array.length-1 => for (int i = 0; i < arr.length-1; i++) 
		*大循环内部的小循环每一次可以看做arr.length-1-i	 => for (int j = 0; j < arr.length-1-i; j++) 
		*就得到了我们最终的代码
		*/

    }

最后的代码

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {12,4,9,112,-6,5};
       
        bubbleSort(array);
		System.out.println("The last sort is "+ Arrays.toString(arr));
    }

	//used array to receive params
    public static void bubbleSort(int[] arr){
        //default sort is desc
        // we known inner process is for i in arr[] length-1 ,any process a max recursion reduce 1
        for (int i = 0; i < arr.length-1; i++) {
            for (int j = 0; j < arr.length-1-i; j++) {
                if(arr[j]>arr[j+1]){
                    int temp = arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }

    }
}

我们在分析的时候是不是发现第五轮循环是无效的,那我们下边进行优化一下
1.我们进行排列的列表有6个元素,我们进行了5次循环,我们进行了n-1次的大循环
2.每次循环的内部操作的步骤是逐步减少的
3.如果某一趟中没有发生交换就跳出循环

	//used array to receive params
    public static void bubbleSort(int[] arr){
      
        //生命一个标识记录循环是否进行了数据交换
        boolean flag =false;
        for (int i = 0; i < arr.length-1; i++) {
            for (int j = 0; j < arr.length-1-i; j++) {
            //我们处理是默认从小到大,如果想要从大到小,倒序排列,我们只需要变更我们的判断条件:arr[j]<arr[j+1]
           
                if(arr[j]>arr[j+1]){
                	flag = true;
                    int temp = arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
            if(!flag){
            	break;
			}else{
				flag=false;
			}
        }

    }

冒泡排序到这儿就结束了,如果有什么不对的地方请大家斧正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值