数据结构复习之顺序表以及链表的方式实现常用的几种排序算法


先提两个问题:

  1. 插入排序为什么比冒泡常用?
    (两者的最优、平均、最差时间复杂度都相同,且都是原地排序——时间复杂度O(1),并且都是)

因为冒泡排序的赋值交换次数比插入排序多(插入排序每次交换只需要一次赋值)

  1. 归并的最差时间复杂度比快排低,但是为什么比快排应用更广泛

因为(没想好)

如何选择

  • 折半查找:记录数较(但不是海量,数据不分布均匀)
  • 桶排序:数据海量,全量排序,数据分布均匀
  • 快速排序:就平均时间而言,快排是所有排序算法中效果最好的
  • 堆排序:数据,求TopN的场景
  • 基数排序:数据,全量排序,但是数据的范围小,数据可以不均匀(比如高考分数排序)【计数排序也行,但是计数排序处理小数或负数需要扩大范围】
    【再者,比如对100万个手机号码做排序,使用计数排序就不好,使用快排也不好。这时候使用基数排序或者桶排序更佳】
    使用基数排序时,如果数字(或字符串)不等长怎么办?
    在后面补0
  • 直接插入:数据较少,或者数据基本有序
  • 若n较小(如n≤50),可采用直接插入或直接选择排序
  • 若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序
    快排、冒泡、插入、shell排序,会受到初始序列的影响。

综述

排序大的分类可以分为两种:内排序和外排序。

内排序是指所有的数据已经读入内存,在内存中进行排序的算法。排序过程中不需要对磁盘进行读写。同时,内排序也一般假定所有用到的辅助空间也可以直接存在于内存中。
外排序即内存中无法保存全部数据,需要进行磁盘访问,每次读入部分数据到内存进行排序。
这里写图片描述

时间复杂度和空间复杂度对比表(有必要记忆下)[1]
这里写图片描述

完整代码-顺序表版本

package list;

import java.util.Arrays;

/**
 * <p>Descirption:分别用顺序表以及链表的方式实现常用的几种排序算法</p>
 *
 * @author 王海
 * @version V1.0
 * @package list
 * @date 2018/4/7 16:25
 * @since 1.0
 */

public class MultiSortArrayAndList {
   
    private static final float[] FORSORT = {
   10, -2, 3, -1111111111.9999999f, 55, 32.8f, 66, 7.8f, 10233.88f, 52222, 45.67f, 13, 654, 99999, 1000000.666f, 77.77f, 3214, 66, 736.2f, 5, 23, 65465, 54783, 9999.999f, 5664645, -33, -66.5566778899f, 2147483647.555f, 2147483647};

    /**
     * 冒泡排序,带标志位(属于交换排序)
     *
     * @param forSort 等待排序的序列
     */

    private void bubbleSort(float[] forSort) {
   
        String name = "冒泡";
        long begin = System.nanoTime();
        if (forSort.length <= 1)  {
   
        printHelper(name, forSort, begin);
        return;
        }
        // 冒泡排序
        for (int i = 0; i < forSort.length - 1; i++) {
   
            // 假设下一次不需要再排序
            boolean sorted = false;
            for (int j = 0; j < forSort.length - i - 1; j++) {
   
                // 这里-i是因为前几次的排序已经沉底了i个数
                if (forSort[j] > forSort[j + 1]) {
   
                    float temp = forSort[j];
                    forSort[j] = forSort[j + 1];
                    forSort[j + 1] = temp;
                    // 排序过了
                    sorted = true;
                }
            }
            if (!sorted) {
   
                break;
            }
        }
        printHelper(name, forSort, begin);
    }

    /**
     * 快速排序(属于交换排序)
     *
     * @param forSort 等待排序的序列
     * @param left    左
     * @param right   右
     */

    private float[] quickSort(float[] forSort, int left, int right) {
   
    	if (forSort.length <= 1) return;
        int i = left;
        int j = right;
        // 递归的结束条件
        if (left < right) {
   
            float benchmark = forSort[left];
            // 下面不能写if,因为并不是说左右指针各移动一次就能保证左右指针“碰头”;完成一次排序
            while (i < j) {
   
                // 右侧比较,小则往前放,大则右指针继续“向左前进”
                while (i < j && forSort[j] > benchmark) {
   
                    --j;
                }
                // while循环退出,如果left还小于right,就该交换数据了
                if (i < j) {
   
                    forSort[i++] = forSort<
  • 4
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值