关于C#冒泡排序的几点优化

冒泡排序基本是我们接触计算机所学到的第一个排序算法,简单的其中其实蕴藏着一些小小的优化,下面就是我分享的一点小小思路

最初版冒泡排序

 public static int BubbleSort(double[] arr)
        {
            int count = 0; //记录执行次数
            double temp;
            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])
                    {
                        //swap
                        temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                    count++;//内循环count
                }
                count++;//外循环count
            }
            return count;
        }

我们给出的数组如下:

编译运行结果如下

 

 可以看到执行了28次,即1累加到7次的内循环再加7次外循环

 考虑到排序过程中若后有序则无需继续考虑,于是可优化内循环,即将最后交换位置作为内循环的上限,即代表后有序后不在考虑后方,优化如下:

 public static int BubbleSort(double[] arr)
        {
            int count = 0;//记录执行次数
            double temp;
            int k = arr.Length - 1;
            int lastPos = 0; //最后一次交换位置
            for (int i = 0; i < arr.Length - 1; i++)
            {
                for(int j = 0; j < k; j++)
                {
                    if (arr[j] > arr[j + 1])
                    {
                        //swap
                        temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                        lastPos = j; 
                    }
                    count++;
                }
                count++;
                k = lastPos;
            }
            return count;
        }

执行结果如下

 可以看到明显少了4次的执行次数(来自内循环),我们将数组换为后有序的能更加明显的看出优化:数组换成

 double[] arr = { 1, 2, 10, 9, 6, 8, 9, 10, 12, 14, 0, 3, 15, 16};

 原始冒泡排序结果如下:

内循环优化后的执行结果如下:

 可以看到,随着后有序的增加,冒泡次数也随之减少,但这时有认真的同学注意到了,为啥我传了个完全有序的数组还执行了7次呢,我们是不是应该定义个bool变量来记录它是否有序,如果第一次未交换则bool值为true,则让它跳出外循环。其实仔细一想,还记得冒泡排序的外循环的意义吗?外循环代表的是已经排好序的个数,再优化外循环如下:

 public static int BubbleSort(double[] arr)
        {
            int count = 0;//记录执行次数
            double temp;
            int k = arr.Length - 1;
            int lastPos;//最后一次交换位置
            for (int i = 0; i <k+1; i++)
            {
                lastPos=0;//关键,可替代bool值
                for(int j = 0; j < k; j++)
                {
                    if (arr[j] > arr[j + 1])
                    {
                        //swap
                        temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                        lastPos = j; 
                    }
                    count++;//内循环count
                }
                count++;//外循环count
                k = lastPos;
                i=0;//关键
            }
            return count;
        }

对同一个数组执行结果如下:

可以看到现在只执行了76次,这时长得帅的同学要问了,为什么是k+1,为什么i要归0,以及为什么lastPos为0可以代替bool值,这三个问题就请大家思考了

既然现在已经优化了后有序了,自然而然我们想到那如何处理前有序呢?,没错,这里给出两种不同的思路。第一种就是双向冒泡或者形象点说上浮和下沉:

  public static int BubbleSort(double[] arr)
        {
            int count = 0;//记录循环次数
            double temp;
            int k = arr.Length - 1;
            int m = 0;
            int lastPos;//记录后有序位置
            int prePos = arr.Length - 1;//记录前有序位置
            for (int i = 0; i < k + 1-m; i++)
            {
                //上浮
                lastPos = 0;
                for (int j = m; j < k; j++)
                {
                    if (arr[j] > arr[j + 1])
                    {
                        //swap
                        temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                        lastPos = j;
                    }
                    count++;//记录内循环1
                }
                k = lastPos;
                //下沉
                //prePos = arr.Length - 1;//可加可不加
                for (int j = k; j > m; j--)
                {
                    if (arr[j] < arr[j - 1])
                    {
                        //swap
                        temp = arr[j];
                        arr[j] = arr[j - 1];
                        arr[j - 1] = temp;
                        prePos = j;
                    }
                    count++;//记录内循环2
                }
                m = prePos;
                count++;//记录外循环
                i=0;//关键,关键,还是tmd关键
            }
            return count;
        }

运行结果如下:

 嗯,基本达到预期效果,与原始冒泡相比基本缩短了一半的执行次数
,即使非前后有序,在过程中凑成的前有序或者后有序也能减少其运行次数

第二种方式暂时还没做好,可能要先鸽一段时间,请见谅

这些就是我能分享给大家的全部了,其实还有一些部分可以进行优化,但能力和精力有限,再加上是第一次写csdn,还请各位大佬多多指教!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值