【算法】 冒泡排序 & 快速排序


 冒泡排序(Bubble Sort)

    


1.算法原理

   

   从后向前,比较相邻的元素。如果第一个比第二个大,就交换他们两个。
   对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
   针对所有的元素重复以上的步骤,除了最后一个。
   持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。



2.算法说明

       

       冒泡排序是一种比较简单的算法,但是第一次看还是觉得有些繁琐。

       它应用了双重嵌套循环,外面的循环是确定本次循环的范围,内部循环是在确定的范围里找到最大的数放到最前。

       这里涉及到有序序列和无序序列,简单来说,就是排好顺序的就是有序的,没排好的就是无序的。

       从它的工作机理来看就是“交换”,从最后那个数开始,和旁边的数比较大小,谁大谁往前,其实就是交换一下,然后就是倒数第二个和倒数三个比较,最后,这个数组的第一个数就是本数组最大的数,那么,我们的有序序列就有了一个数!就是最大那个数!

        这时候,外部循环进行了一次,内部循环整个循环一圈~

        然后外部循环的范围就会减1,其实它一直在确定无序序列的范围。然后内循环是找最大。

        总之,就这样,循环往复........



举个例子~

        如果有10个数,第一次从10个数中(外循环确定)找最大的数放在第一的位置(内循环整体循环一次可得到);

        第二次从9个数中(还是外循环确定的范围,第一个数已经是最大的了)找最大的数放在这9个数的第一的位置(内循环再次整体循环)

        就这样一直排下去....


 




 快速排序(Quick Sort)


1.算法原理

       

       设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。


一趟快速排序的算法是:
       1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
       2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
       3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
       4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
       5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。



2.算法说明

      

        快速排序是对冒泡排序的一种改进。

        冒泡排序通常不会使用,但是学习它可以帮助理解快速排序,那么快速排序到底改进了哪些???

        在冒泡排序中,我们是和旁边的数比较,然后让大数一步步的从后面换到前面,这样,未免有些笨,因为在日常生活中,如果我们给学生排队的话,肯定是让高个子的直接排到前面,低的排在后面,然后再微调,没人会让最高的那个一次一次的从后面“交换”上来,太慢了。。。

        所以,这里引入一个二分法的理念。

        简单来说,就是把大的放一块,小的放一块。然后继续划分,这样做的好处就是相比冒泡排序有种一步到位的感觉,因为它一下就把大数和小数分到差不多的位置,而不是笨笨的一点点移上去。





 代码对比

    

下面是冒泡排序和快速排序的代码(C#版)

static void Main(string[] args)
        {

            int numberCount;
            int[] numbers;

            Console.WriteLine("请问您要对多少个数字进行排序?");
            numberCount = Convert.ToInt32(Console.ReadLine());

            //生成指定数量的随机数
            numbers = new int[numberCount];
            System.Random rnd = new System.Random();
            for (int i = 0; i < numberCount; i++)
            {
                numbers[i] = rnd.Next(1, numberCount); ;
            }
            Console.WriteLine();



            //冒泡排序
            System.Diagnostics.Stopwatch watch1 = new System.Diagnostics.Stopwatch();
            watch1.Start();
            for (int i = 0; i < numbers.Length - 1; i++)
            {
                for (int j = 0; j < numbers.Length - 1 - i; j++)
                {
                    if (numbers[j] > numbers[j + 1])
                    {
                        int temp = numbers[j];
                        numbers[j] = numbers[j + 1];
                        numbers[j + 1] = temp;
                    }
                }
            }
            watch1.Stop();
            Console.WriteLine("冒泡排序 耗费时间为: {0} 毫秒", watch1.ElapsedMilliseconds);
            Console.WriteLine();


                      

            //快速排序
            System.Diagnostics.Stopwatch watch5 = new System.Diagnostics.Stopwatch();
            watch5.Start();            
            sort(numbers, 0, numbers.Length - 1);             
            watch5.Stop();
            Console.WriteLine("快速排序 耗费时间为: {0} 毫秒", watch5.ElapsedMilliseconds);
            Console.WriteLine();


            Console.ReadKey();
        }


        private static int sortUnit(int[] array, int low, int high)
        {
            int key = array[low];
            while (low < high)
            {
                /*从后向前搜索比key小的值*/
                while (array[high] >= key && high > low)
                    --high; 
                /*比key小的放左边*/
                array[low] = array[high];   
                /*从前向后搜索比key大的值,比key大的放右边*/
                while (array[low] <= key && high > low)
                    ++low; 
                /*比key大的放右边*/
                array[high] = array[low];
            }
            /*左边都比key小,右边都比key大。//将key放在游标当前位置。//此时low等于high */
            array[low] = key;
            return high;
        }    

            
        public static void sort(int[] array, int low, int high)
        {
         
            if (low >= high)
                return; 
            /*完成一次单元排序*/
            int index = sortUnit(array, low, high); 
            /*对左边单元进行排序*/
            sort(array, low, index - 1);
            /*对右边单元进行排序*/
            sort(array, index + 1, high);
        } 
 }


输入的结果为:

【算法】 冒泡排序 & 快速排序_第1张图片





 空间复杂度 & 时间复杂度

    


   

       在这里要涉及到空间复杂度和时间复杂度的问题,简单来说就是需要多少内存来处理和需要多少时间来处理。

       通常情况下,降低空间复杂度会引起时间复杂度的上升。其实这也很好理解,同样的任务量,人少时间用的就多,人多时间用的就少。当然,这也不是绝对的,如果你的方法上升到更高的维度,说不定你所用的空间和时间都会减少。





 总结

    

      对算法的研究还会继续进行下去,他们可以很好帮助我们优化我们的代码。

      这些凝结的智慧会对我们有很大启发,站在巨人之上,学习并超越。



 

你可能感兴趣的:(………算法)