关于冒泡排序的优化

先来看基本的冒泡排序:
原理很简单,两层循环,外层确定遍历趟数,内层遍历数组,按照排序规则正序或者倒序比较相邻两个数字大小,并交换他们的位置。

        static void Main(string[] args)
        {
            int[] nums = new int[] { 8,7,6,5,4,3,2,1,0 };
            NumOrder(nums);
        }
        static void NumOrder(int[] nums)
        {
            int ci = 0;
            int temp = 0;
            for (int i = 0; i < nums.Length - 1; i++)
            {
                for (int j = 0; j < nums.Length - i - 1; j++)
                {
                    if (nums[j] > nums[j + 1])
                    {
                        temp = nums[j];
                        nums[j] = nums[j + 1];
                        nums[j + 1] = temp;
                    }
                    ci++;
                }
            }
            foreach (var num in nums)
            {
                Console.Write(num + ",");
            }
            Console.WriteLine($"循环了{ci}次");
        }

在这里插入图片描述
但是现在好像不管要排序的数组是不是有序,都需要循环这么多遍!当我们把数组换成有序的,循环次数还是跟之前无序的一样。我们可以来优化一下,当第一次循环发现无位置交换的情况下,就证明这个数组是有序的。我们就可以结束循环,返回数组了

        static void Main(string[] args)
        {
            int[] nums = new int[] { 0,1,2,3,4,5,6,7,8};
            NumOrder(nums);
        }
        static void NumOrder(int[] nums)
        {
            int ci = 0;
            int temp = 0;
            int isOrderly=1;//默认为有序
            for (int i = 0; i < nums.Length - 1; i++)
            {
                for (int j = 0; j < nums.Length - i - 1; j++)
                {
                    if (nums[j] > nums[j + 1])
                    {
                        temp = nums[j];
                        nums[j] = nums[j + 1];
                        nums[j + 1] = temp;
                        isOrderly=0;//如果位置发生了交换,就设置为无序
                    }
                    ci++;
                }
               if (isOrderly == 1)//如果第一次内层循环未发生位置交换,就代表数组是有序的,所以跳出循环
                    break;
            }
            foreach (var num in nums)
            {
                Console.Write(num + ",");
            }
            Console.WriteLine($"循环了{ci}次");
        }

在这里插入图片描述
循环次数变成了8次。

那我们还能再优化优化么?肯定可以耶,我们来仔细分析一下排序过程:
在这里插入图片描述
你会发现从最后一次比较的位置下标开始,前面部分都是无序的,后面都是有序的已比较过的:
在这里插入图片描述
所以,后半部分已经有序的,下次循环排序时候是不是可以避免掉。我们可以通过记录最后一次发生位置交换的下标,用这个下标来控制内循环次数。看代码:

   static void Main(string[] args)
        {
            int[] nums = new int[] { 9, 8, 7, 6, 5,10,11,12,13,14,15};
            NumOrder(nums);
        }
        static void NumOrder(int[] nums)
        {
            int ci = 0;
            int temp = 0;
            int sub = nums.Length - 1;//控制内层循环次数
            int n;//记录最后一次交换的位置
            int isOrderly;
            for (int i = 0; i < nums.Length-1; i++)
            {
                n = 0;
                isOrderly = 1;//默认为有序
                for (int j = 0; j < sub; j++)
                {
                    if (nums[j] > nums[j + 1])
                    {
                        temp = nums[j];
                        nums[j] = nums[j + 1];
                        nums[j + 1] = temp;
                        isOrderly = 0;//如果位置发生了交换,就设置为无序
                        n = j;//记录最后一次交换的位置
                    }
                    ci++;
                }
                if (isOrderly == 1)//如果第一次内层循环未发生位置交换,就代表数组是有序的所以跳出循环
                    break;
                sub = n;
            }
            foreach (var num in nums)
            {
                Console.Write(num + ",");
            }
            Console.WriteLine($"循环了{ci}次");
        }

可以用数组测试一下,比如代码里的那个,改动之前运行结果:
在这里插入图片描述
记录下标,控制内循环次数之后:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值