排序算法(dart实现)

排序算法

[toc]

10大经典排序比较

image.png

冒泡、选择、插入、归并、快速、希尔、堆排序,属于比较排序(Comparison Sorting)

算法的静态网站
2.visualization

排序算法的稳定性

如果相等的2个元素,在排序前后的相对位置保持不变,那么这是稳定的排序算法

  • 排序前 :5,1,3(a),4,7,3(b)
  • 稳定排序:1,3(a),3(b),4,5,7
  • 不稳定排序:1,3(b),3(a),4,5,7

对自定义对象排序时,稳定性影响最终的排序结果

算法 是否稳定性
冒泡排序

原地算法

  • 不依赖额外的资源或者依赖少数的额外资源,仅依靠输出来覆盖输入
  • 空间复杂度为O(1)的都可以任务实施原地算法

非原地算法,称为Not-in-placke或者Out-of-placle
十大排序的是否为原地算法如上图

提前准备类

抽象类


import '../tools/date_utl.dart';

///
/// Author: liyanjun
/// /// Date: 2020-11-01 10:41:34
/// FilePath: /algorithm/sort/sort.dart
/// Description: 排序的超类
///
abstract class Sort<T extends Comparable<T>> implements Comparable<Sort<T>> {
  // abstract class Sort<T implements Comparable<T>>   {
  List<T> list;
  int cmpCount = 0; //比较次数
  int swapCount = 0; //交换次数
  int time; //耗时时间

  setList(List<T> list) {
    this.list = list;
  }

  sortPrint() {
    if (list == null || list.length < 2) return;
    int begin = DateUtil.getNowDateMs();
    sort();
    int end = DateUtil.getNowDateMs();
    time = end - begin;
  }

  sort();

  ///
  /// Author: liyanjun
  /// description:
  /// 返回值等于0,代表 list[i1] == list[i2]
  /// 返回值小于0,代表 list[i1] < list[i2]
  /// 返回值大于0,代表 list[i1] > list[i2]
  ///
  ///
  int cmpWithIndex(int i1, int i2) {
    cmpCount += 1;
    return list[i1].compareTo(list[i2]);
  }

  ///
  /// Author: liyanjun
  /// description:
  // 返回值等于0,代表 v1 == v2
  /// 返回值小于0,代表 v1  < v2
  /// 返回值大于0,代表 v1  > v2
  int cmpElement(T v1, T v2) {
    cmpCount += 1;
    return v1.compareTo(v2);
  }

  ///
  /// Author: liyanjun
  /// description: 交换两个索引位置
  ///

  void swap(int i1, int i2) {
    swapCount += 1;
    T tmp = list[i1];
    list[i1] = list[i2];
    list[i2] = tmp;
  }

  ///
  /// Author: liyanjun43
  /// description: 格式化
  ///
  String _numberString(int number) {
    if (number < 10000) return "$number";

    if (number < 100000000) return "${(number / 10000.0).toStringAsFixed(2)}万";

    return "${(number / 100000000.0).toStringAsFixed(2)}亿";
  }

  ///
  /// Author: liyanjun
  /// description:按照时间排序,如果时间相等,比较比较次数,如果再相等比较交互次数
  ///
  @override
  int compareTo(Sort o) {
    int result = (time - o.time);
    if (result != 0) return result;
    result = cmpCount - o.cmpCount;
    if (result != 0) return result;
    return swapCount - o.swapCount;
  }

  @override
  String toString() {
    // TODO: implement toString
    String timeStr = "耗时:${time / 1000.0}s (${time}ms)";
    String compareCountStr = "比较:${_numberString(cmpCount)}";
    String swapCountStr = "交换:${_numberString(swapCount)}";
    // String stableStr = "稳定性:" + isStable();
    return "【" +
        this.runtimeType.toString() +
        "】\n"
        // + stableStr + " \t"
        +
        timeStr +
        " \t" +
        compareCountStr +
        "\t " +
        swapCountStr +
        "\n" +
        "-----------------";
    // return super.toString();
  }
}

数组操作的类

import 'dart:math';

class IntergerTools {
  ///
  /// Author: liyanjun
  /// description: 生成随机数
  ///
  static List<int> random(int count, int min, int max) {
    if (count <= 0 || min > max) return null;
    List<int> array = List<int>(count);
    int delta = max - min + 1;
    for (int i = 0; i < count; i++) {
      array[i] = min + Random().nextInt(delta);
    }
    return array;
  }

  ///
  /// Author: liyanjun
  /// description: 合并两个list
  ///
  static List combine(List array1, List array2) {
    if (array1 == null || array2 == null) return null;
    List array = [];
    for (int i = 0; i < array1.length; i++) {
      array[i] = array1[i];
    }
    for (int i = 0; i < array2.length; i++) {
      array[i + array1.length] = array2[i];
    }
    return array;
  }

  ///
  /// Author: liyanjun
  /// description:
  ///
  static List same(int count, int unsameCount) {
    if (count <= 0 || unsameCount > count) return null;
    List array = [];
    for (int i = 0; i < unsameCount; i++) {
      array[i] = unsameCount - i;
    }
    for (int i = unsameCount; i < count; i++) {
      array[i] = unsameCount + 1;
    }
    return array;
  }

   static List<int> headTailAscOrder(int min, int max, int disorderCount) {
    List<int> array = ascOrder(min, max);
    if (disorderCount > array.length) return array;

    int begin = (array.length - disorderCount) >> 1;

    reverse(array, begin, begin + disorderCount);
    return array;
  }

   static List<int> centerAscOrder(int min, int max, int disorderCount) {
    List<int> array = ascOrder(min, max);
    if (disorderCount > array.length) return array;
    int left = disorderCount >> 1;
    reverse(array, 0, left);

    int right = disorderCount - left;
    reverse(array, array.length - right, array.length);
    return array;
  }

     static List<int> headAscOrder(int min, int max, int disorderCount) {
    List<int> array = ascOrder(min, max);
    if (disorderCount > array.length) return array;
    reverse(array, array.length - disorderCount, array.length);
    return array;
  }

   static List<int> tailAscOrder(int min, int max, int disorderCount) {
    List<int> array = ascOrder(min, max);
    if (disorderCount > array.length) return array;
    reverse(array, 0, disorderCount);
    return array;
  }

  static List<int> ascOrder(int min, int max) {
    if (min > max) return null;
    List<int> array = List<int>(max - min + 1);
    for (int i = 0; i < array.length; i++) {
      array[i] = min++;
    }
    return array;
  }

  static List<int> descOrder(int min, int max) {
    if (min > max) return null;
    List<int> array = List<int>(max - min + 1);
    for (int i = 0; i < array.length; i++) {
      array[i] = max--;
    }
    return array;
  }

  /**
   * 反转一个数组,索引范围是[begin, end)
   */
   static void reverse(List<int> array, int begin, int end) {
    int count = (end - begin) >> 1;
    int sum = begin + end - 1;
    for (int i = begin; i < begin + count; i++) {
        int j = sum - i;
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
  }



   static bool isAscOrder(List<int> array) {
    if (array == null || array.length == 0) return false;
    for (int i = 1; i < array.length; i++) {
        if (array[i - 1] > array[i]) return false;
    }
    return true;
  }

  
}

时间类

import 'date_utl.dart';

///
/// Date: 2020-10-31 22:51:08
/// FilePath: /sort/tools/times_tools.dart
/// Description: 测试时间的工具类
///


class TimesTools {
    static  final DateFormat _fmt = DateFormat.DEFAULT;
    
    
     static void test(String title, Function task) {
        if (task == null) return;
        title = (title == null) ? "" : ("【" + title + "】");
        print(title);
    print("开始:${DateUtil.getDateStrByDateTime(DateTime.now(),format: _fmt)}");
        int begin =  DateUtil.getNowDateMs();
        task();
        int end =  DateUtil.getNowDateMs();
      print("结束 ${DateUtil.getDateStrByDateTime(DateTime.now(),format: _fmt)}");
        double delta = (end - begin) / 1000.0;
      print("耗时:$delta 秒");
        print("-------------------------------------");
    }
}

断言判断类

///
/// Author: liyanjun
/// Date: 2020-11-01 10:10:37
/// FilePath: /algorithm/tools/assert.dart
/// Description: 利用断言判断结果
///

class Asserts {
static  void  test(bool value ){
  try {
    if (value == false) {
      throw Exception("测试未通过");
    }
  } catch (e) {
     print('异常: $e');
     rethrow;
  }
  }
}

排序算法对比



main(List<String> args) {
  List<int> list = IntergerTools.random(10000, 1, 20000); //生成10000个数,最小是1,最大是20000
  // List<int> list = IntergerTools.random(10, 1, 20); //生成10000个数,最小是1,最大是20000
  List<Sort> sortList = [
      HeapSort<num>(),//堆排序
    SelectSort<num>(),//选择排序
    BubbleSort2<num>(),//冒泡排序
    BubbleSort1<num>(),//冒泡排序优化1 完全有序,提前终止
    BubbleSort<num>(),//冒泡排序优化2 如果序列尾部已经局部有序,可以记录最后1次交换的位置,减少比较次数
    InsertSort<num>(),//插入排序
    InsertSort1<num>(),//插入排序优化1:改为挪动不是替换
    InsertSort2<num>(),//插入排序优化2:改为二分查找
    MergeSort<num>(),//归并排序
    QuickSort<num>(),//快速排序
    ShellSort<num>(),//希尔排序
  ];
  testSorts(list, sortList);
}

void testSorts(List<int> list, List<Sort> sorts) {
  // print('排序前 :$list');
  for (Sort sort in sorts) {
    List<int> newList = List.from(list);
    sort.setList(newList);
    sort.sortPrint();
    Asserts.test(IntergerTools.isAscOrder(sort.list));
    //  print('排序后 :${sort.list}');
  }
  sorts.sort(); //比较
  for (Sort sort in sorts) {
    print(sort);
  }
}
    

结果

【QuickSort<num>】
耗时:0.005s (5ms)     比较:16.30万    交换:6536
-----------------
【ShellSort<num>】
耗时:0.006s (6ms)     比较:19.66万    交换:0
-----------------
【HeapSort<num>】
耗时:0.006s (6ms)     比较:23.53万    交换:9999
-----------------
【InsertSort2<num>】
耗时:0.084s (84ms)    比较:11.91万    交换:0
-----------------
【InsertSort1<num>】
耗时:0.115s (115ms)   比较:2533.10万  交换:0
-----------------
【SelectSort<num>】
耗时:0.146s (146ms)   比较:4999.50万  交换:9999
-----------------
【InsertSort<num>】
耗时:0.178s (178ms)   比较:2533.10万  交换:2532.10万
-----------------
【BubbleSort1<num>】
耗时:0.488s (488ms)   比较:4999.23万  交换:2532.10万
-----------------
【BubbleSort2<num>】
耗时:0.506s (506ms)   比较:4997.58万  交换:2532.10万
-----------------
【BubbleSort<num>】
耗时:0.506s (506ms)   比较:4999.50万  交换:2532.10万
-----------------
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269