0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

十大经典排序算法动画与解析

电子工程师 来源:lq 2019-02-25 09:20 次阅读

排序算法是《数据结构与算法》中最基本的算法之一。

排序算法可以分为内部排序和外部排序。内部排序是数据记录在内存中进行排序。而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。

常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。

用一张图概括:

时间复杂度与空间复杂度

关于时间复杂度:

平方阶 (O(n2)) 排序 各类简单排序:直接插入、直接选择和冒泡排序;

线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序;

O(n1+§)) 排序,§ 是介于 0 和 1 之间的常数。 希尔排序;

线性阶 (O(n)) 排序 基数排序,此外还有桶、箱排序。

关于稳定性:

稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序;

不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序。

一、冒泡排序

1.1 算法步骤

比较相邻的元素。如果第一个比第二个大,就交换他们两个。

对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

针对所有的元素重复以上的步骤,除了最后一个。

持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

1.2 动画演示

冒泡排序动画演示

1.3 参考代码

1//Java代码实现 2publicclassBubbleSortimplementsIArraySort{ 3 4@Override 5publicint[]sort(int[]sourceArray)throwsException{ 6//对arr进行拷贝,不改变参数内容 7int[]arr=Arrays.copyOf(sourceArray,sourceArray.length); 8 9for(inti=1;i< arr.length; i++) {10            // 设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。11            boolean flag = true;1213            for (int j = 0; j < arr.length - i; j++) {14                if (arr[j] >arr[j+1]){15inttmp=arr[j];16arr[j]=arr[j+1];17arr[j+1]=tmp;1819flag=false;20}21}2223if(flag){24break;25}26}27returnarr;28}29}

二、选择排序

2.1 算法步骤

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置

再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

重复第二步,直到所有元素均排序完毕。

2.2 动画演示

选择排序动画演示

2.3 参考代码

1//Java代码实现 2publicclassSelectionSortimplementsIArraySort{ 3 4@Override 5publicint[]sort(int[]sourceArray)throwsException{ 6int[]arr=Arrays.copyOf(sourceArray,sourceArray.length); 7 8//总共要经过N-1轮比较 9for(inti=0;i< arr.length - 1; i++) {10            int min = i;1112            // 每轮需要比较的次数 N-i13            for (int j = i + 1; j < arr.length; j++) {14                if (arr[j] < arr[min]) {15                    // 记录目前能找到的最小值元素的下标16                    min = j;17                }18            }1920            // 将找到的最小值和i位置所在的值进行交换21            if (i != min) {22                int tmp = arr[i];23                arr[i] = arr[min];24                arr[min] = tmp;25            }2627        }28        return arr;29    }30}

三、插入排序

3.1 算法步骤

将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

3.2 动画演示

插入排序动画演示

3.3 参考代码

1//Java代码实现 2publicclassInsertSortimplementsIArraySort{ 3 4@Override 5publicint[]sort(int[]sourceArray)throwsException{ 6//对arr进行拷贝,不改变参数内容 7int[]arr=Arrays.copyOf(sourceArray,sourceArray.length); 8 9//从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的10for(inti=1;i< arr.length; i++) {1112            // 记录要插入的数据13            int tmp = arr[i];1415            // 从已经排序的序列最右边的开始比较,找到比其小的数16            int j = i;17            while (j >0&&tmp< arr[j - 1]) {18                arr[j] = arr[j - 1];19                j--;20            }2122            // 存在比其小的数,插入23            if (j != i) {24                arr[j] = tmp;25            }2627        }28        return arr;29    }30}

四、希尔排序

4.1 算法步骤

选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;

按增量序列个数 k,对序列进行 k 趟排序;

每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

4.2 动画演示

希尔排序动画演示

4.3 参考代码

1//Java代码实现 2publicclassShellSortimplementsIArraySort{ 3 4@Override 5publicint[]sort(int[]sourceArray)throwsException{ 6//对arr进行拷贝,不改变参数内容 7int[]arr=Arrays.copyOf(sourceArray,sourceArray.length); 8 9intgap=1;10while(gap< arr.length) {11            gap = gap * 3 + 1;12        }1314        while (gap >0){15for(inti=gap;i< arr.length; i++) {16                int tmp = arr[i];17                int j = i - gap;18                while (j >=0&&arr[j]>tmp){19arr[j+gap]=arr[j];20j-=gap;21}22arr[j+gap]=tmp;23}24gap=(int)Math.floor(gap/3);25}2627returnarr;28}29}

五、归并排序

5.1 算法步骤

申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

设定两个指针,最初位置分别为两个已经排序序列的起始位置;

比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

重复步骤 3 直到某一指针达到序列尾;

将另一序列剩下的所有元素直接复制到合并序列尾。

5.2 动画演示

归并排序动画演示

5.3 参考代码

1//Java代码实现 publicclassMergeSortimplementsIArraySort{ 2 3@Override 4publicint[]sort(int[]sourceArray)throwsException{ 5//对arr进行拷贝,不改变参数内容 6int[]arr=Arrays.copyOf(sourceArray,sourceArray.length); 7 8if(arr.length< 2) { 9            return arr;10        }11        int middle = (int) Math.floor(arr.length / 2);1213        int[] left = Arrays.copyOfRange(arr, 0, middle);14        int[] right = Arrays.copyOfRange(arr, middle, arr.length);1516        return merge(sort(left), sort(right));17    }1819    protected int[] merge(int[] left, int[] right) {20        int[] result = new int[left.length + right.length];21        int i = 0;22        while (left.length >0&&right.length>0){23if(left[0]<= right[0]) {24                result[i++] = left[0];25                left = Arrays.copyOfRange(left, 1, left.length);26            } else {27                result[i++] = right[0];28                right = Arrays.copyOfRange(right, 1, right.length);29            }30        }3132        while (left.length >0){33result[i++]=left[0];34left=Arrays.copyOfRange(left,1,left.length);35}3637while(right.length>0){38result[i++]=right[0];39right=Arrays.copyOfRange(right,1,right.length);40}4142returnresult;43}4445}

六、快速排序

算法步骤

从数列中挑出一个元素,称为 “基准”(pivot);

重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

6.2 动画演示

快速排序动画演示

6.3 参考代码

1//Java代码实现 2publicclassQuickSortimplementsIArraySort{ 3 4@Override 5publicint[]sort(int[]sourceArray)throwsException{ 6//对arr进行拷贝,不改变参数内容 7int[]arr=Arrays.copyOf(sourceArray,sourceArray.length); 8 9returnquickSort(arr,0,arr.length-1);10}1112privateint[]quickSort(int[]arr,intleft,intright){13if(left< right) {14            int partitionIndex = partition(arr, left, right);15            quickSort(arr, left, partitionIndex - 1);16            quickSort(arr, partitionIndex + 1, right);17        }18        return arr;19    }2021    private int partition(int[] arr, int left, int right) {22        // 设定基准值(pivot)23        int pivot = left;24        int index = pivot + 1;25        for (int i = index; i <= right; i++) {26            if (arr[i] < arr[pivot]) {27                swap(arr, i, index);28                index++;29            }30        }31        swap(arr, pivot, index - 1);32        return index - 1;33    }3435    private void swap(int[] arr, int i, int j) {36        int temp = arr[i];37        arr[i] = arr[j];38        arr[j] = temp;39    }4041}

七、堆排序

7.1 算法步骤

创建一个堆 H[0……n-1];

把堆首(最大值)和堆尾互换;

把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;

重复步骤 2,直到堆的尺寸为 1。

7.2 动画演示

堆排序动画演示

7.3 参考代码

1//Java代码实现 2publicclassHeapSortimplementsIArraySort{ 3 4@Override 5publicint[]sort(int[]sourceArray)throwsException{ 6//对arr进行拷贝,不改变参数内容 7int[]arr=Arrays.copyOf(sourceArray,sourceArray.length); 8 9intlen=arr.length;1011buildMaxHeap(arr,len);1213for(inti=len-1;i>0;i--){14swap(arr,0,i);15len--;16heapify(arr,0,len);17}18returnarr;19}2021privatevoidbuildMaxHeap(int[]arr,intlen){22for(inti=(int)Math.floor(len/2);i>=0;i--){23heapify(arr,i,len);24}25}2627privatevoidheapify(int[]arr,inti,intlen){28intleft=2*i+1;29intright=2*i+2;30intlargest=i;3132if(left< len && arr[left] >arr[largest]){33largest=left;34}3536if(right< len && arr[right] >arr[largest]){37largest=right;38}3940if(largest!=i){41swap(arr,i,largest);42heapify(arr,largest,len);43}44}4546privatevoidswap(int[]arr,inti,intj){47inttemp=arr[i];48arr[i]=arr[j];49arr[j]=temp;50}5152}

八、计数排序

8.1 算法步骤

花O(n)的时间扫描一下整个序列 A,获取最小值 min 和最大值 max

开辟一块新的空间创建新的数组 B,长度为 ( max - min + 1)

数组 B 中 index 的元素记录的值是 A 中某元素出现的次数

最后输出目标整数序列,具体的逻辑是遍历数组 B,输出相应元素以及对应的个数

8.2 动画演示

计数排序动画演示

8.3 参考代码

1//Java代码实现 2publicclassCountingSortimplementsIArraySort{ 3 4@Override 5publicint[]sort(int[]sourceArray)throwsException{ 6//对arr进行拷贝,不改变参数内容 7int[]arr=Arrays.copyOf(sourceArray,sourceArray.length); 8 9intmaxValue=getMaxValue(arr);1011returncountingSort(arr,maxValue);12}1314privateint[]countingSort(int[]arr,intmaxValue){15intbucketLen=maxValue+1;16int[]bucket=newint[bucketLen];1718for(intvalue:arr){19bucket[value]++;20}2122intsortedIndex=0;23for(intj=0;j< bucketLen; j++) {24            while (bucket[j] >0){25arr[sortedIndex++]=j;26bucket[j]--;27}28}29returnarr;30}3132privateintgetMaxValue(int[]arr){33intmaxValue=arr[0];34for(intvalue:arr){35if(maxValue< value) {36                maxValue = value;37            }38        }39        return maxValue;40    }4142}

九、桶排序

9.1 算法步骤

设置固定数量的空桶。

把数据放到对应的桶中。

对每个不为空的桶中数据进行排序。

拼接不为空的桶中数据,得到结果

9.2 动画演示

桶排序动画演示

9.3 参考代码

1//Java代码实现 2publicclassBucketSortimplementsIArraySort{ 3 4privatestaticfinalInsertSortinsertSort=newInsertSort(); 5 6@Override 7publicint[]sort(int[]sourceArray)throwsException{ 8//对arr进行拷贝,不改变参数内容 9int[]arr=Arrays.copyOf(sourceArray,sourceArray.length);1011returnbucketSort(arr,5);12}1314privateint[]bucketSort(int[]arr,intbucketSize)throwsException{15if(arr.length==0){16returnarr;17}1819intminValue=arr[0];20intmaxValue=arr[0];21for(intvalue:arr){22if(value< minValue) {23                minValue = value;24            } else if (value >maxValue){25maxValue=value;26}27}2829intbucketCount=(int)Math.floor((maxValue-minValue)/bucketSize)+1;30int[][]buckets=newint[bucketCount][0];3132//利用映射函数将数据分配到各个桶中33for(inti=0;i< arr.length; i++) {34            int index = (int) Math.floor((arr[i] - minValue) / bucketSize);35            buckets[index] = arrAppend(buckets[index], arr[i]);36        }3738        int arrIndex = 0;39        for (int[] bucket : buckets) {40            if (bucket.length <= 0) {41                continue;42            }43            // 对每个桶进行排序,这里使用了插入排序44            bucket = insertSort.sort(bucket);45            for (int value : bucket) {46                arr[arrIndex++] = value;47            }48        }4950        return arr;51    }5253    /**54     * 自动扩容,并保存数据55     *56     * @param arr57     * @param value58     */59    private int[] arrAppend(int[] arr, int value) {60        arr = Arrays.copyOf(arr, arr.length + 1);61        arr[arr.length - 1] = value;62        return arr;63    }6465}

十、基数排序

10.1 算法步骤

将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零

从最低位开始,依次进行一次排序

从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列

10.2 动画演示

基数排序动画演示

10.3 参考代码

1//Java代码实现 2publicclassRadixSortimplementsIArraySort{ 3 4@Override 5publicint[]sort(int[]sourceArray)throwsException{ 6//对arr进行拷贝,不改变参数内容 7int[]arr=Arrays.copyOf(sourceArray,sourceArray.length); 8 9intmaxDigit=getMaxDigit(arr);10returnradixSort(arr,maxDigit);11}1213/**14*获取最高位数15*/16privateintgetMaxDigit(int[]arr){17intmaxValue=getMaxValue(arr);18returngetNumLenght(maxValue);19}2021privateintgetMaxValue(int[]arr){22intmaxValue=arr[0];23for(intvalue:arr){24if(maxValue< value) {25                maxValue = value;26            }27        }28        return maxValue;29    }3031    protected int getNumLenght(long num) {32        if (num == 0) {33            return 1;34        }35        int lenght = 0;36        for (long temp = num; temp != 0; temp /= 10) {37            lenght++;38        }39        return lenght;40    }4142    private int[] radixSort(int[] arr, int maxDigit) {43        int mod = 10;44        int dev = 1;4546        for (int i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {47            // 考虑负数的情况,这里扩展一倍队列数,其中 [0-9]对应负数,[10-19]对应正数 (bucket + 10)48            int[][] counter = new int[mod * 2][0];4950            for (int j = 0; j < arr.length; j++) {51                int bucket = ((arr[j] % mod) / dev) + mod;52                counter[bucket] = arrayAppend(counter[bucket], arr[j]);53            }5455            int pos = 0;56            for (int[] bucket : counter) {57                for (int value : bucket) {58                    arr[pos++] = value;59                }60            }61        }6263        return arr;64    }65    private int[] arrayAppend(int[] arr, int value) {66        arr = Arrays.copyOf(arr, arr.length + 1);67        arr[arr.length - 1] = value;68        return arr;69    }70}

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 代码
    +关注

    关注

    30

    文章

    4553

    浏览量

    66690
  • 数据结构
    +关注

    关注

    3

    文章

    562

    浏览量

    39898
  • 排序算法
    +关注

    关注

    0

    文章

    50

    浏览量

    10019

原文标题:十大经典排序算法动画与解析,看我就够了

文章出处:【微信号:rgznai100,微信公众号:rgznai100】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    动图展示C语言十大经典排序算法

    以前也零零碎碎发过一些排序算法,但排版都不太好,又重新整理一次,排序算法是数据结构的重要部分,系统地学习很有必要。
    发表于 11-08 09:45 435次阅读

    C语言经典排序算法总结

    本文将通过动态演示+代码的形式系统地总结十大经典排序算法
    发表于 06-05 10:56 387次阅读
    C语言<b class='flag-5'>经典</b><b class='flag-5'>排序</b><b class='flag-5'>算法</b>总结

    十大排序算法总结

    排序算法是最经典算法知识。因为其实现代码短,应该广,在面试中经常会问到排序算法及其相关的问题。
    的头像 发表于 12-20 10:39 711次阅读

    C语言十大滤波算法

    C语言十大滤波算法
    发表于 08-15 18:41

    世界十大设计团队的经典设计策略

    ` 本帖最后由 gk320830 于 2015-3-4 14:11 编辑 世界十大设计团队的经典设计策略`
    发表于 09-13 19:44

    数据挖掘十大经典算法,你都知道哪些!

    的所有需求。而这三类里又包含许多经典算法。而今天,小编就给大家介绍下数据挖掘中最经典十大算法,希望它对你有所帮助。一、 分类决策树
    发表于 11-06 17:02

    单片机滤波算法

    为什么别人的单片机算法不是百度里面的什么十大经典算法二十很复杂的算法,谁能提供一个算法应用在嵌入式里滤ad采样 温度这些
    发表于 03-12 17:05

    【免费领取】运放十大经典电路(视频21集)

    运放十大经典电路(视频21集)本项目使用单个运算放大器搭建出各种经典电路,其中包括电压跟随器,同相放大电路,反相放大电路,加法器,减法器(差分放大),比较器,滞回比较器,三角波发生器,方波发生器
    发表于 10-19 14:01

    运放十大经典电路(视频21集)【免费领取!!】

    运放十大经典电路(视频21集)本项目使用单个运算放大器搭建出各种经典电路,其中包括电压跟随器,同相放大电路,反相放大电路,加法器,减法器(差分放大),比较器,滞回比较器,三角波发生器,方波发生器
    发表于 12-07 17:11

    电池管理中的十大经典理论

    电池管理中的十大经典理论 1、彼得原理      每个组织都是由各种不同的职位、等级或阶层的排列所组成,每个人都隶属于
    发表于 11-06 15:43 689次阅读

    数学建模十大经典算法

    电子专业单片机相关知识学习教材资料——数学建模十大经典算法
    发表于 08-08 18:20 0次下载

    C语言动图演示十大经典排序算法(含代码)

    本文将通过动态演示+代码的形式系统地总结十大经典排序算法
    的头像 发表于 01-29 11:34 1089次阅读

    动图演示C语言10大经典排序算法(含代码)

    本文将通过 动态演示+代码 的形式系统地总结十大经典排序算法排序算法 算法分类 十种常见
    的头像 发表于 02-07 01:24 442次阅读

    用Python实现十大经典排序算法(附动图)

    冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要
    的头像 发表于 03-13 09:29 1687次阅读

    常见排序算法分类

    本文将通过动态演示+代码的形式系统地总结十大经典排序算法排序算法 算法分类 —— 十种常见
    的头像 发表于 06-22 14:49 622次阅读
    常见<b class='flag-5'>排序</b><b class='flag-5'>算法</b>分类