快速排序(dart实现)

快速排序

[toc]

快速排序1960年由查尔斯安东尼理查德霍尔(Charles Antony Richard Hoare,缩写为C. A. R. Hoare)提出的
作者行业内昵称为东尼霍尔(Tony Hoare)

执行流程

  1. 从序列中选择一个轴点元素 (pivot)
    • 段设每次选择0位置的元素为轴点元素
  2. 利用pivot将序列分割成2个子序列
    • 将小于pivot的元素放在pivot前面(左侧)
    • 将大于pivot的元素放在pivot后面(右侧)
    • 等于pivot的元素放哪边都可以
  3. 对子序列进行1、2操作
    • 直到不能再分割(子序列中只剩下1个元素)

本质:逐渐将每一个元素都转化成轴点元素

选择轴点流程

如图


image.png
  1. 构造两个索引begin和end,begin指向头元素,end指向末尾元素,选择将第一个元素变成轴点6a,备份6a
  2. 从末尾开始扫描,也就是从end开始扫描,发现7>6,让end--,end指向5,如图第2行
  3. 再比较5<6,让5覆盖6a元素的位置,begin++,如图第3行,5是黑色表示是垃圾数据,该位置随时可能会被覆盖
  4. 再开始begin开始扫描,发现8>6,让8覆盖黑色5的位置,原来8的位置变成黑色,如果第4行,执行end--,end指向9
  5. 再比较9>6,直接让end--,end指向4,如果5行
  6. 再比较4<6,让4覆盖8a黑色位置,如图6行,begin++,end变成黑色即为垃圾位置
  7. 再比较8b>6,让8b覆盖4的位置,并执行end--,如图行7
  8. 比较6b=6a,可以不动,也可以移动,这里让6b移动,也就是放入8b黑色的位置,并执行begin++,如图行8
  9. 比较2<6,直接begin++,如图行9
  10. 此时begin==end,将6a放入此位置,轴点生成完成

代码


class QuickSort<T extends Comparable<T>> extends Sort<T> {
  @override
  sort() {
    int begin = 0;
    int end = list.length;
    _sort(begin,end);
  }

  ///
  /// Author: liyanjun
  /// description:
  ///对[[begin,end)],左闭右开的,范围内元素进行快速排序
  _sort(int begin, int end) {
    //元素必须大于2
    if (end - begin < 2) return;
    int mid = _pivotIndex(begin, end);//O(n)
    _sort(begin, mid); //左边子序列快速排序 
    _sort(mid + 1, end); //右边子序列快速排序
  }

  ///
  /// Author: liyanjun
  /// description:
  /// 构造出 [begin, end) 范围的轴点元素,返回轴点元素的最终位置
  ///
  int _pivotIndex(int begin, int end) {
    //将begin元素备份
    T pivot = list[begin];
    //由于是左闭右开,所以要让end--
    end--;
    while (begin < end) {//确定变换方向后继续执行
      while (begin < end) {//后面扫描
        if (cmpElement(list[end], pivot) > 0) {
          //右边元素大于轴点元素
          end--;
        } else {
          //右边元素小于等于轴点元素
          list[begin++] = list[end];
          break;
        }
      }
      while (begin < end) {//前面扫描
        if (cmpElement(list[begin], pivot) < 0) {
          //左边元素小于轴点元素
          begin++;
        } else {
          //右边元素>=轴点元素
          list[end--] = list[begin];
          break;
        }
      }
    }
    list[begin] = pivot; //// 将轴点元素放入最终的位置
    return begin; //此时begin==end
  }
}

验证


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>(),
    // BubbleSort<num>(),
    // InsertSort<num>(),
    // InsertSort1<num>(),
    // InsertSort2<num>(),
    // MergeSort<num>(),
    QuickSort<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);
  }
}

执行结果

排序前 :[7, 9, 6, 15, 10, 19, 16, 18, 18, 6]
排序后 :[6, 6, 7, 9, 10, 15, 16, 18, 18, 19]
【QuickSort<num>】
耗时:0.001s (1ms)     比较:22    交换:0
-----------------

时间复杂度

  • 在轴点左右元素数量比较均匀的情况下,同时也是最好的情况
    • 左边T(n/2),右边T(n/2)
    • \therefore T(n) = 2 ∗ T(n/2) + O (n) = O(nlogn)
  • 如果轴点左右元素数量极度不均匀,最坏情况
    • 假如左边n-1个,右边1个
    • 左边T(n-1),右边左边T(1)
    • \therefore T(n) = T(n-1) + O (n) = O(n^2)
  • 最好、平均时间复杂度:O(nlogn)
  • 最坏时间复杂度:O(n^2)
  • 由于递归调用的缘故,空间复杂度:O(logn)
  • 属于不稳定排序

为了降低最坏情况的出现概率,一般采取的做法是

随机选择轴点元素

优化代码

 ///
  /// Author: liyanjun
  /// description:
  /// 构造出 [begin, end) 范围的轴点元素,返回轴点元素的最终位置
  ///
  int _pivotIndex(int begin, int end) {
    
  // 随机选择一个元素跟begin位置进行交换
    //因为 Random().nextInt(max)是包括max的,所以应该end-1
        swap(begin, begin + Random().nextInt(end-1-begin));
    //将begin元素备份
    T pivot = list[begin];
    //由于是左闭右开,所以要让end--
    end--;
    while (begin < end) {//确定变换方向后继续执行  思想,掉头用两个while循环
      while (begin < end) {//后面扫描
        if (cmpElement(list[end], pivot) > 0) {
          //右边元素大于轴点元素
          end--;
        } else {
          //右边元素小于等于轴点元素
          list[begin++] = list[end];
          break;
        }
      }
      while (begin < end) {//前面扫描
        if (cmpElement(list[begin], pivot) < 0) {
          //左边元素小于轴点元素
          begin++;
        } else {
          //右边元素>=轴点元素
          list[end--] = list[begin];
          break;
        }
      }
    }
    list[begin] = pivot; //// 将轴点元素放入最终的位置
    return begin; //此时begin==end
  }
}

与轴点相等的元素

cmp 位置的判断分别改为 ≤、≥ 会起到什么效果
假如原数组为
[3,3,3,3,3,3]
如果判断为 ≤、≥ ,则会导致轴点元素处于两端,造成最坏情况的时间复杂度,所以不用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341