匡菲 发表于 2025-6-2 00:26:31

重生之数据结构与算法----常见排序算法(二)

简介

上文中,我们讲到了选择排序,冒泡排序,插入排序,希尔排序。
都是相对比较简单的实现方式,因为它们都是以人的思维,维护一个index,将index与周围元素逐步对比。直到整个数组有序。
但越是效率高的算法,反而要越接近计算的的思维。否则非常难以突破O(N^2)的桎梏。
而接下来的几种效率高算法,则是一步一步接近计算机的思维,实现排序高效。
二叉树前序遍历:快速排序

快速排序的核心思路是:先将一个元素排好序,然后递归排序剩下的元素
这里可能难以理解,这说的是什么逼话?我们再拆解一下。

[*]在数组中随机选一个作为排序元素

^
pivot
[*]进行排序,将大于pivot的元素放右边,小于的放左边

       ^
       pivot
[*]递归重复以上步骤,寻找新的切分元素,然后交换。
[,3,]
^      ^    ^
pivot2 pivot pivot3
[*]直到全部排序完成
根据上面的思维描述,我们可以写出一个代码框架,并将它们抽象成一颗二叉树
      public void Sort(int[] arr,int left,int right)
      {
            if (left > right)
                return;

            //进行切分,并将P排好序
            int p = Partition(arr, left, right);

            //对左右子数
            //是不是类似二叉树的前序遍历?
            Sort(arr, left, p - 1);
            Sort(arr, p + 1, right);
      }
               
                        /// <summary>
      /// 分区操作
      /// </summary>
      /// <param name="arr"></param>
      /// <param name="left"></param>
      /// <param name="right"></param>
      /// <returns></returns>
      private static int Partition(int[] arr, int left, int right)
      {
            // 选择最右边的元素作为基准元素
            int pivot = arr;
            int i = left - 1;

            for (int j = left; j < right; j++)
            {
                if (arr <= pivot)
                {
                  i++;
                  (arr, arr) = (arr, arr);
                }
            }
            (arr, arr) = (arr, arr);
            return i + 1;
      }其实没什么变化,相对之前实现的优先级队列来说。只是把数组作为参数传递,实现原地排序而已。
复杂度分析


[*]时间复杂度
O(n log n) ,因为要对swim/sink要对每个元素调用
[*]空间复杂度
O(1)
[*]排序稳定性
不稳定,因为skin过程中,要将堆顶元素,与堆尾元素交换。 违背了相邻元素交换的原则,所以不稳定。
[*]原地排序
是,我们的优化过程就是为了结果原地排序的问题。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 重生之数据结构与算法----常见排序算法(二)