前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >算法-排序(上)

算法-排序(上)

原创
作者头像
用户9327954
修改于 2021-12-26 14:53:22
修改于 2021-12-26 14:53:22
3870
举报
文章被收录于专栏:会爬的乌龟会爬的乌龟

概述

排序(Sorting)是将一组对象按照规定的次序重新排列的过程,排序往往是为检索服务的。

排序算法的稳定性:相同键值的两个记录在排序前后相对位置的变化情况。稳定性是排序算法本身的特性,与数据无关。

排序的分类:

  1. 内部排序(Internal Sorting):待排序记录全部放在计算机内存中进行的排序过程。
  2. 外部排序(External Sorting):待排序的记录数量很大,内存不能存储全部记录,需要对外存进行访问的排序过程。

排序算法的分类:交换排序、插入排序、选择排序、归并排序。

交换排序

基本思想:比较两个记录键值的大小,如果这两个记录键值的大小出现逆序,则交换这两个记录。

冒泡排序(Bubble Sorting)

基本思想:把相邻的元素两两比较,当一个元素大于右侧相邻元素时,交换它们的位置;当一个元素小于或等于右侧相邻元素时,位置不变。

冒泡排序图.png
冒泡排序图.png

代码实现:

代码语言:txt
AI代码解释
复制
    private static void sort(int[] array) {
        int len = array.length;
        for (int i = 0; i < len - 1; i++) {
            for (int j = 1; j < len - i; j++) {
                if (array[j - 1] > array[j]) {
                    array[j] = array[j - 1] ^ array[j];
                    array[j - 1] = array[j] ^ array[j - 1];
                    array[j] = array[j] ^ array[j - 1];
                }
            }
        }
    }

冒泡排序总共遍历"元素数量-1"轮,每轮都要遍历所有元素,所以平均时间复杂度是O(n²)。

冒泡排序的优化1

冒泡排序优化1.png
冒泡排序优化1.png

如上种情况,数列在第一轮排序后已经有序,那么剩下的几轮排序就可以不执行了。

代码可进行如下优化:

代码语言:txt
AI代码解释
复制
    private static void sort(int[] array) {
        int len = array.length;
        for (int i = 0; i < len - 1; i++) {
            // 有序标记
            boolean isSorted = true;
            for (int j = 1; j < len - i; j++) {
                if (array[j - 1] > array[j]) {
                    array[j] = array[j - 1] ^ array[j];
                    array[j - 1] = array[j] ^ array[j - 1];
                    array[j] = array[j] ^ array[j - 1];
                    isSorted = false;
                }
            }
            if (isSorted) {
                return;
            }
        }
    }

冒泡排序的优化2

冒泡排序优化2.png
冒泡排序优化2.png

如上图,数列右边元素是有序的,可是每一轮还是要进行比较操作。这正是需要优化的地方。问题关键在于对数列有序区的界定。解决办法是在每一轮排序后,记录最后一次元素交换的位置,该位置即为无序数列的边界,再往后就是有序区。

代码可进行如下优化:

代码语言:txt
AI代码解释
复制
    private static void sort(int[] array) {
        int len = array.length;
        //最后一次交换的位置
        int lastExIndex = 0;
        // 边界,每次比较到此为止
        int exBorder = array.length;
        for (int i = 0; i < len - 1; i++) {
            boolean isSorted = true;
            for (int j = 1; j < exBorder; j++) {
                if (array[j - 1] > array[j]) {
                    array[j] = array[j - 1] ^ array[j];
                    array[j - 1] = array[j] ^ array[j - 1];
                    array[j] = array[j] ^ array[j - 1];
                    isSorted = false;
                    //更新为最后一次交换元素的位置
                    lastExIndex = j;
                }
            }
            exBorder = lastExIndex;
            if (isSorted) {
                return;
            }
        }
    }

鸡尾酒排序(Cocktail Sorting)

鸡尾酒排序又称双向冒泡排序,元素的比较和交换过程是双向的。排序的过程就像钟摆一样,第1轮从左到右,第2轮从右到左,第3轮再从左到右。。。。如下图所示:

鸡尾酒排序.png
鸡尾酒排序.png

代码实现如下:

代码语言:txt
AI代码解释
复制
    private static void sort(int[] array) {
        int len = array.length;
        for (int i = 0; i < len / 2; i++) {
            boolean isSorted = true;
            //从左向右比较和交换
            for (int j = i; j < len - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    array[j] = array[j] ^ array[j + 1];
                    array[j + 1] = array[j] ^ array[j + 1];
                    array[j] = array[j] ^ array[j + 1];
                    isSorted = false;
                }
            }
            if (isSorted) {
                return;
            }
            isSorted = true;
            //从右向左比较和交换
            for (int j = len - i - 2; j > i; j--) {
                if (array[j] < array[j - 1]) {
                    array[j] = array[j] ^ array[j - 1];
                    array[j - 1] = array[j] ^ array[j - 1];
                    array[j] = array[j] ^ array[j - 1];
                    isSorted = false;
                }
            }
            if (isSorted) {
                return;
            }
        }
    }

鸡尾酒排序能够在特定条件下,减少排序的回合数,以序列(2,3,4,5,1)为例,鸡尾酒排序只需要访问两次(左右各一次 )序列就可以完成排序,但如果使用冒泡排序则需要四次。

快速排序(Quick Sorting)

快速排序是从冒泡排序演变而来的,同冒泡排序一样,快速排序也属于交换排序。

冒泡排序在每一轮中只把1个元素冒泡到数列的一端,而快速排序是在每一轮中挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移到数列的另一边,从而把数列拆解成两个总分。

大致流程如下:

快排的思路.png
快排的思路.png

这种思路叫分治法,原数列在每一轮都被拆分成两部分,每一部分在下一轮又被拆分成部分,直到不可两分为止。

基准元素,英文是pivot,在分治过程中,以基准元素为中心,把其他元素移动到它的左右两边。

代码实现的方式有两种:

  • 双边循环法
  • 单边循环法

双边循环法

基本思想:是从数组的两边交替遍历。过程下图所示:

快排(双指针).png
快排(双指针).png

代码实现:

代码语言:txt
AI代码解释
复制
    public static void main(String[] args) {
        int[] array = {4, 3, 6, 9, 8, 1, 2, 5};
        sort(array, 0, array.length - 1);
        System.out.println(Arrays.toString(array));
    }   
	/**
     * 双指针法
     */
    private static void sort(int[] array, int left, int right) {
        if (left >= right) {
            return;
        }
        int divideIndex = quickPartition(array, left, right);
        sort(array, left, divideIndex - 1);
        sort(array, divideIndex + 1, right);

    }

    private static int quickPartition(int[] array, int left, int right) {
        //基准值(选择左边第一个元素)
        int pivot = array[left];
        while (left < right) {
            // 从右边第一个元素开始与基准值比较
            while ((left < right) && (array[right] >= pivot)) {
                right--;
            }
            array[left] = array[right];
            while ((left < right) && (array[left] <= pivot)) {
                left++;
            }
            array[right] = array[left];
        }
        array[left] = pivot;
        return left;
    }

可以用一棵二叉树表示算法的执行过程,以数列{4,3,6,9,8,1,2,5}为例,如下图所示

快排(二叉树).png
快排(二叉树).png

递归调用的顺序是 -->sort(0,7)-->sort(0,2)-->sort(0,0)-->sort(2,2)-->sort(4,7)-->sort(4,5)-->sort(4,3)-->sort(5,5)-->sort(7,7)。可以看出该算法的执行过程实质是对应二叉树的先序遍历过程。

单边循环法

基本思想:从数组的一边进行遍历和交换,具体过程如下图所示:

快排(单指针).png
快排(单指针).png

代码实现如下:

代码语言:txt
AI代码解释
复制
    /**
     * 单指针
     */
    private static void sort(int[] array, int left, int right) {
        if (left >= right) {
            return;
        }
        int divideIndex = quickPartition(array, left, right);
        sort(array, left, divideIndex - 1);
        sort(array, divideIndex + 1, right);

    }

    private static int quickPartition(int[] array, int left, int right) {
        //基准值(选择左边第一个元素)
        int pivot = array[left];
        int mark = left;
        for (int i = left; i <= right; i++) {
            if (array[i] < pivot && ++mark <i) {
                array[i] = array[i]^array[mark];
                array[mark] = array[i]^array[mark];
                array[i] = array[i] ^ array[mark];
            }
        }
        array[left] = array[mark];
        array[mark] = pivot;
        return mark;
    }

通过上面所讲的实现方法中,我们了解到了 快速排序的递归过程类似一棵二叉树的遍历过程,二叉树的遍历是可以通过非递归的方式实现的。二叉树的遍历分成DFS(深度优先遍历)和BFS(广度优先遍历),DFS的非递归遍历是通过栈实现的,BFS是借助队列实现。下面我们分别通过栈和队列实现快速排序。

栈非递归实现

代码语言:txt
AI代码解释
复制
    private static void sortByStack(int[] array) {
        Stack<Range> stack = new Stack<>();
        stack.push(new Range(0, array.length - 1));
        while (!stack.empty()) {
            Range range = stack.pop();
            int left = range.getLeft();
            int right = range.getRight();
            if (left < right) {
                int divideIndex = quickPartition(array, left, right);
                stack.push(new Range(divideIndex + 1, right));
                stack.push(new Range(left, divideIndex - 1));
            }
        }
    }

    /**
     * 单边循环
     */
    private static int quickPartition(int[] array, int left, int right) {
        //基准值(选择左边第一个元素)
        int pivot = array[left];
        int mark = left;
        for (int i = left; i <= right; i++) {
            if (array[i] < pivot && ++mark < i) {
                array[i] = array[i] ^ array[mark];
                array[mark] = array[i] ^ array[mark];
                array[i] = array[i] ^ array[mark];
            }
        }
        array[left] = array[mark];
        array[mark] = pivot;
        return mark;
    }


    public static class Range {
        private final int left;
        private final int right;

        public Range(int left, int right) {
            this.left = left;
            this.right = right;
        }

        public int getLeft() {
            return left;
        }
        public int getRight() {
            return right;
        }
    }

队列的非递归实现

代码语言:txt
AI代码解释
复制
   private static void sortByQueue(int[] array) {
        Queue<Range> queue = new LinkedList<>();
        queue.offer(new Range(0, array.length - 1));

        while (!queue.isEmpty()) {
            Range range = queue.poll();
            int left = range.getLeft();
            int right = range.getRight();
            if (left < right) {
                int divideIndex = quickPartition(array, left, right);
                queue.offer(new Range(divideIndex + 1, right));
                queue.offer(new Range(left, divideIndex - 1));
            }
        }
    }

    /**
     * 单边循环
     */
    private static int quickPartition(int[] array, int left, int right) {
        //基准值(选择左边第一个元素)
        int pivot = array[left];
        int mark = left;
        for (int i = left; i <= right; i++) {
            if (array[i] < pivot && ++mark < i) {
                array[i] = array[i] ^ array[mark];
                array[mark] = array[i] ^ array[mark];
                array[i] = array[i] ^ array[mark];
            }
        }
        array[left] = array[mark];
        array[mark] = pivot;
        return mark;
    }


    public static class Range {
        private final int left;
        private final int right;

        public Range(int left, int right) {
            this.left = left;
            this.right = right;
        }

        public int getLeft() {
            return left;
        }

        public int getRight() {
            return right;
        }
    }

基准元素的选择

上面快速排序实现中,我们都是选择数列中第1个元素为基准元素,这种情况在大多数情况是没有问题的。但是,

假如有一个原本逆序的数列,期望排序成顺序数列,那么会出现如下情况:

快排(基准元素的选择).png
快排(基准元素的选择).png

如上,整个数列没有被分成两半,在这种情况下,待排序的数列中第1个元素要么是最小值,要么是最大值,根本无法发挥分治法的优势。快速排序的时间复杂度退化为O(n²)。

如何规避这种情况发生呢?

我们可以随机选择一个元素作为基准元素,并且让基准元素和数列首元素交换位置。

复杂度分析

通过上面的分析,我们可知空间复杂度是O(logn),平均时间复杂度是O(nlogn),最坏时间复杂度是O(n²)。

双轴快速排序(DualPivot Quicksort)

双轴快速排序是俄罗斯程序员Vladimir Yaroslavskiy 在2009年开发出来的一种排序算法,与上面所讲的传统快排不同的是,它有两个基准值。

双轴快速排序的执行过程,我们引用原始论文 文中介绍:

双轴排序论文.PNG
双轴排序论文.PNG

P1、P2为选择的两个pivot轴,其指针位置用left和right变量表示。我们再定义三个指针L、K和G,其中位置见下图。三个指针区分出了四个分区。算法步骤如下:

  1. 选择两个轴元素P1、P2。例如图中选择第一个元素aleft =P1,最后一个元素aright=P2。
  2. 限定P1<P2( 如果不是,则交换P1、P2)。这样我们就可以分出如下部分:Parit I left,L-1为<P1部分,Part II L,K-1为>=P1且<=P2部分,PartIII G+1,right-1为>P2部分,Part IVK,G为还没有确定的部分。
  3. 针对当前Part IV中的aK,与P1和P2比较,比较后放入Part I II III 中的一个。
  4. 调整L、K、G到适合的位置。
  5. 重复4、5步直到K>G。也就是说PartIV的元素全部分散到Part I II III中,最后是三个Part。
  6. 将P1放入Part I的最后一个位置,P2放入Part III的前一个位置(或者第一个位置)。这样就确定了P1和P2的位置。
  7. 对于PartI II III ,重复1-6步。

代码实现如下:

代码语言:txt
AI代码解释
复制
    private static void sort(int[] arr, int start, int end) {
        if (start > end) {
            return;
        }
        if (arr[start] > arr[end]) {
            swap(arr, start, end);
        }
        //储存最左侧和最右侧的值
        int pivot1 = arr[start];
        int pivot2 = arr[end];

        //(start,left]:左侧小于等于pivot1  [right,end)大于pivot2
        int left = start;
        int right = end;
        int m = left + 1;

        while (m < right) {
            if (arr[m] < pivot1) {
                //和左侧交换
                swap(arr, ++left, m++);
            } else if (arr[m] <= pivot2) {
                //在中间的情况
                m++;
            } else {
                //如果全部大于pivot2直接跳出外层循环
                while (arr[--right] > pivot2) {
                    if (right == m)
                        break;
                }
                if (m >= right) {
                    break;
                }
                swap(arr, m, right);
            }
        }

        swap(arr, start, left);
        swap(arr, end, right);

        sort(arr, start, left - 1);
        sort(arr, left + 1, right - 1);
        sort(arr, right + 1, end);
    }

    private static void swap(int[] array, int left, int right) {
        int temp = array[left];
        array[left] = array[right];
        array[right] = temp;
    }

下面我用图例来演示上面代码的执行过程:

双轴快排.png
双轴快排.png

从上可知双轴快速排序的时间复杂度与传统的快速排序是一样的。但实际执行的时候的双轴快速排序会更快,关于这个问题有一篇论文 Why Is Dual-Pivot Quicksort Fast? 作出了解释

论文中提到:

对比经典快速排序,双轴快速排序算法使用了更多的比较和指令,那么它在实践中怎么会更快?即理论和实际是有差异的!原因很可能与一种被称为“内存墙”或“冯.诺依曼瓶颈”的现象有关:长期以来,处理速度的增长速度远远以快于内存带宽。

关于“内存墙”,论文是这样描述的:

CPU速度在过去25年中以46%的平均年增长率增长,而内存带宽,即在给定时间内RAM和CPU之间可传输的数据量,每年增长37%。

如果CPU和内存传输速度之间的不平衡继续呈指数级增长,那么在将来的某个时候,CPU的任何进一步改进都将是徒劳的:处理器一直在等待数据;我们撞上了“内存墙”。

因此,论文作者提到我们在排序时不因仅考虑CPU的速度,还应考虑内存的速度,CPU和内存是否匹配等影响。

同时给出了另一种比较排序算法优劣的方法:扫描元素个数。

对于数组中一个元素的访问arrayi称为一次扫描。但是对于同一个下标,并且对应的值也不变的话,即使访问多次也只算一次,不管这个访问是读还是写。

为什么只算一次呢?由于有CPU高速缓存存在,再次访问数组同一下标的元素不需要访问内存,因此比访问一个新的下标元素时间少很多。

因此统计CPU与内存之间的数据流量大小也就把这个比较慢的内存因素考虑进去了。

扫描的元素与缓存未命中相关:

经典快速排序的一个分区步骤只扫描一次,结果是扫描了n个元素。在双轴快速排序的分区中,索引k和g一起扫描一次,但是索引ℓ 第二次扫描最左边的段。平均而言,后者包含所有元素的三分之一,产生4/3n扫描元素总数。Java 7快速排序(双轴快速排序)比Java 6版本(经典快速排序)节省了12%的元素扫描。

结论

关于交换排序的算法的内容就聊到这里,本文介绍了几种交换排序的实现原理及特点。

其中比较难理解的快速排序,在JAVA源代码中DualPivotQuicksort类有相关实现,这个类由Vladimir Yaroslavskiy, Jon Bentley, Josh Bloch编写,是一个高效的排序算法,里面不仅用到快排,还有插入排序、归并排序、计数排序。

参考资料

冯诺依曼瓶颈

Why Is Dual-Pivot Quicksort Fast?

Dual-Pivot Quicksort algorithm

《算法(第4版)》作者: 美 Robert Sedgewick / 美 Kevin Wayne

《漫画算法》作者: 魏梦舒

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
排序算法的简单实现(冒泡和快排)
原始的冒泡排序是稳定排序。由于该排序的每一轮要遍历所以元素,轮转的次数和元素数量相当,所以时间复杂度是 O(N^2)。
希希里之海
2018/12/27
4970
还不会十大排序,是准备家里蹲吗!?
代码的效果正好和图片相反,其实冒泡排序作为最简单的排序方法之一,基于的是一个这样的概念:两两交换,比较双方数值大的放在高位,数值小的则放在低位。
音视频开发进阶
2020/05/26
3770
还不会十大排序,是准备家里蹲吗!?
漫画:什么是鸡尾酒排序?
冒泡排序的每一个元素都可以像小气泡一样,根据自身大小,一点一点向着数组的一侧移动。算法的每一轮从都是从左到右比较元素,进行单向的位置交换。
小灰
2022/07/05
2100
漫画:什么是鸡尾酒排序?
为什么快速排序算法效率比较高?
快速排序算法是非常高效的一个排序算法,在众多的排序算法里面其无论在时间复杂度还是空间复杂度都是比较低的。因此作为一个程序员,我们很有必要学习和理解快排的原理。
我是攻城师
2018/09/30
9.7K0
为什么快速排序算法效率比较高?
一文搞定十大经典排序算法
下面我们来逐一分析十大经典排序算法,主要围绕下列问题展开: 1、算法的基本思想是什么? 2、算法的代码实现? 3、算法的时间复杂度是多少?(平均、最好、最坏)什么情况下最好?什么情况下最坏? 4、算法的空间复杂度是多少? 5、算法的稳定性如何?
matinal
2020/11/27
5910
一文搞定十大经典排序算法
Arrays.sort实现原理-双轴快排
jdk1.7中Arrays.sort主要核心用的双轴快排,是一种改进的快排。先来复习一下大学里学习的普通快排算法。
张伦聪zhangluncong
2022/10/26
5280
java冒泡排序和快速排序
一、冒泡排序 1.算法介绍 设排序表长为n,从后向前或者从前向后两两比较相邻元素的值,如果两者的相对次序不对(A[i-1] > A[i]),则交换它们,其结果是将最小的元素交换到待排序序列的第一个位置
三哥
2018/06/15
1.3K0
极客算法训练笔记(六),十大经典排序之希尔排序,快速排序
排序算法的衡量指标我这里不再重复,上一篇我已经列举分析的很清楚了,但是非常重要,没看到我上一篇的小伙伴墙裂推荐,这里给一个直通车票 极客算法训练笔记(五),十大经典排序之冒泡,选择,插入排序 。
阿甘的码路
2020/11/12
4930
极客算法训练笔记(六),十大经典排序之希尔排序,快速排序
上个厕所的功夫,就学会了“快速排序”算法
快速排序,顾名思义就是一种以效率快为特色的排序算法,快速排序(Quicksort)是对冒泡排序的一种改进。由英国计算机专家:托尼·霍尔(Tony Hoare)在1960年提出。
陈哈哈
2020/07/03
7770
DualPivotQuickSort 双轴快速排序 源码 笔记
这个算法是Arrays.java中给基本类型的数据排序使用的具体实现。它针对每种基本类型都做了实现,实现的方式有稍微的差异,但是思路都是相同的,所以这里只挑了int类型的排序来看。
yuxiaofei93
2018/09/11
1.1K0
八大排序老忘?视图结合高效写出代码!
相信很多友友在笔试或者面试的前,如果遇到排序的问题,心中就在想,就是那样那样。可是,一到面对的时候,总是心里一咯噔,沃擦,我怎么说不上来了?本文我会把自己如何快速学习排序的过程分享出来。
麦洛
2021/07/05
2800
八大排序老忘?视图结合高效写出代码!
八大排序算法总结与java实现
概述 因为健忘,加上对各种排序算法理解不深刻,过段时间面对排序就蒙了。所以决定对我们常见的这几种排序算法进行统一总结。首先罗列一下常见的十大排序算法: 请点击此处输入图片描述 我们讨论的这八大排序算法的实现可以参考我的Github:SortAlgorithms,其中也包括了排序测试模块[Test.java]和排序算法对比模块[Bench.java],大家可以试运行。 它们都属于内部排序,也就是只考虑数据量较小仅需要使用内存的排序算法,他们之间关系如下: 请点击此处输入图片描述 一、直接插入排序(In
企鹅号小编
2018/01/18
1.1K0
八大排序算法总结与java实现
八大排序算法(java实现) 冒泡排序 快速排序 堆排序 归并排序 等
一、直接插入 - 1.基本思路 - 2.代码实现 - 3.时间复杂度和空间复杂度二、希尔排序 - 1.基本思路 - 2.代码实现 - 3.时间复杂度和空间复杂度三、简单选择 - 1.基本思路 - 2.代码实现 - 3.时间复杂度和空间复杂度四、堆排序 - 1.基本思路 - 2.代码实现 - 3.时间复杂度和空间复杂度五、冒泡排序 - 1.基本思路 - 2.代码实现 - 3.时间复杂度和空间复杂度六、快速排序 - 1.基本思路 - 2.代码实现 - 3.时间复杂度和空间复杂度七、归并排序 - 1.基本思路 - 2.代码实现 - 3.时间复杂度和空间复杂度八、基数排序 - 1.基本思路 - 2.代码实现 - 3.时间复杂度和空间复杂度总结
用户7886150
2020/12/04
2720
各种排序算法的分析及java&python实现
排序大的分类可以分为两种:内排序和外排序。在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序。下面讲的排序都是属于内排序。 内排序有可以分为以下几类: (1)、插入排序:直接插入排序、二分法插入排序、希尔排序。 (2)、选择排序:简单选择排序、堆排序。 (3)、交换排序:冒泡排序、快速排序。 (4)、归并排序 (5)、基数排序 1、插入排序 思想 每步将一个待排序的记录,按其顺序码大小插入到前面已经排序的字序列的合适位置,直到全部插入排序完为止。 1.1 直接插入排序
石晓文
2018/04/11
9730
各种排序算法的分析及java&python实现
这或许是东半球分析十大排序算法最好的一篇文章
本文全长 14237 字,配有 70 张图片和动画,和你一起一步步看懂排序算法的运行过程。
五分钟学算法
2019/06/18
5860
这或许是东半球分析十大排序算法最好的一篇文章
JavaScript算法-排序算法
对计算机中存储的数据执行的两种最常见操作是排序和索引。下述阐述的排序方式,暂且都是用数组进行测试(从小到大)。
奋飛
2021/08/30
5170
JavaScript算法-排序算法
动画+原理+代码+优化,解读十大经典排序算法
排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。用一张图概括:
用户1655470
2018/12/28
4810
动画+原理+代码+优化,解读十大经典排序算法
常见排序算法详解
作为程序员,时时刻刻都要与算法打交道,其中排序算法算是比较常见的一种。而在面试程序员岗位中, 不出意外,排序算法也是比较常见的考量之一。因此我们有必要了解和掌握各种常见排序算法。 这个篇文章记录了几种常见的排序算法,并各种排序算法极端情况的优劣想,供学习和参考。
终身幼稚园
2019/07/19
5430
常见排序算法详解
排序算法
基本思想: 我们将一个待排序序列分为有序区和无序区(一般开始的时候将第一个元素作为有序区,剩下的元素作为无序区),每次将无序区的第一个元素作为待插入记录,按大小插入到前面已经排好的有序区中的适当位置,直到记录全部插入完成为止。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面)
Cloud-Cloudys
2020/07/07
3840
手撕十大排序算法
为了方便在程序种测试算法的步骤和正确性,为此写了一个通用的代码如下,方便于在main方法里进行调试
ma布
2024/10/21
1280
手撕十大排序算法
相关推荐
排序算法的简单实现(冒泡和快排)
更多 >
LV.0
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档