基础算法之冒泡排序

冒泡排序

排序约定:

​
   public abstract class Sort<T> where   T:IComparable<T>
    {
        public abstract void sort(T[] nums);

        /// <summary>
        /// 第一位比第二位小
        /// </summary>
        /// <param name="t1"></param>
        /// <param name="t2"></param>
        /// <returns></returns>
        protected bool less(T t1, T t2)
        {
            return t1.CompareTo(t2) < 0;
        }

        protected void Swap(int i,int j,T[] nums)
        {
            T temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }

​

约定接口:比较函数,交换函数。

 

冒泡排序的思想是从0->i 依次比较相邻元素,如果大于或者小于,就交换位置,每遍历一次,最大/最小的就跑到最高位置去, 走一次遍历可以把一个数排到最高位置, 因此需要N*N-i 次  ,算法复杂度为:On2。

因为遍历一次就可以得到一位排序好的数, 因此在第二次遍历的需要减去i;如果遍历一次,一次都不需要交换,则不需要再排序了。

 基本冒泡排序

     public override void sort(T[] nums)
        {
             
            for (int i = 0; i < nums.Length - 1; i++)
            {
                bool isNeed = false;
                for (int j = 1; j < nums.Length - i; j++)
                {
                    if (less(nums[j],nums[j-1]))
                    {
                        Swap(j,j-1,nums);                         
                        isNeed = true;
                    }
                }

                if (!isNeed)
                {
                    break;

                }
            }
        }

 

关于优化

1.基于冒泡排序的 优化,在需要交换的时候,还可以记录下 当前需要交换的位置,把它视作边界;

排序后有序的边界,然后下次就不用全部再走一遍了。

2.  升级版鸡尾酒排序,  思路就是一前一后遍历,  排序就像摆钟 , 这种情况适合在数组中已经有很多有序的数的情况下, 排序次数在以上是最少的。

 

优化边界版:  

这种 情况是在于  2,1,3,4,5,6,7,8 这种情况, 按照上面的逻辑  ,最后一轮  发现 2 ,1交换,然后继续,2,3, 3,4 ....直到结束, 实际上后面都是有序的,再比较也没意义。

因此只需要记录下边界  ,遍历到下标为1  ,就可以了。

 /// <summary>
        /// 冒泡排序 优化版 , 加外框,在每轮排序后,记录下来最后一次元素交换的位置,
        /// 该位置即为无序数组的边界, 往后就是有序数组了
        /// </summary>
        /// <param name="nums"></param>
        public void BorderBubleSort(T[] nums)
        {
            
            for (int i = 0; i < nums.Length - 1; i++)
            {
                bool isNeed = false;
                int border = nums.Length - 1;
                for (int j = 1; j <border; j++)
                {
                    if (less(nums[j], nums[j - 1]))
                    {
                        Swap(j, j - 1, nums);
                        isNeed = true;
                        border = j;
                    }
                }

                if (!isNeed)
                {
                    break;

                }
            }
        }

 

 升级版鸡尾酒排序

 加了边界优化,每加边界这里是border就是 nums.length-1-i, 双向冒泡排序。

鸡尾酒排序,排序过程是双向的,因此可以防止出现很多有序的情况还继续比较;

这个非常适用于  数组已经是大部分有序的情况。

         /// <summary>
        /// 升级版 冒泡排序-鸡尾酒排序,  一前  一 后,
        /// </summary>
        /// <param name="nums"></param>
        public void CocktailSort(T[] nums)
        {
            for (int i = 0; i < nums.Length/2; i++)
            {
                bool isSort = false;
                int border = nums.Length - 1;
                for (int j = i; j <border; j++)//从 i
                {
                    if (less(nums[j],nums[j+1]))
                    {
                        Swap(j,j+1,nums);
                        isSort = true;
                        border = j;
                    }
                }

                if (!isSort)
                {
                    break;
                }

                isSort = false;
                border = nums.Length - 1;
                for (int j = border; j >i; j--)
                {
                    if (less(nums[j], nums[j - 1]))
                    {
                        Swap(j, j - 1, nums);
                        isSort = true;
                        border = j;
                    }
                }

                if (!isSort)
                {
                   break; 
                }
            }
        }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值