【算法】八大排序算法

注:

1)本文的所有图解均来自百度图片搜索,侵删
2)代码使用java编写
3)本文主要用于记录我对排序算法的理解,若有错误,望指出

1、冒泡排序

思路

1)每次循环中,比较相邻的两个数,大的往下沉,那么一轮循环后,最大的数就放在最后了
2)由于上一次循环,已经把最大的数沉到最后了,因此下一次循环的需要比较的元素个数就减1
3)直至需要比较的元素个数为0

图解

冒泡排序

代码实现

  public static void bubleSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    // 每次循环次数n,每次都比上一次少排一次
    for (int e = arr.length - 1; e > 0; e--) {
            for (int i = 0; i < e; i++) {
                if (arr[i] > arr[i + 1]) {
                  int tmp = arr[i];
                  arr[i] = arr[i + 1];
                  arr[i + 1] = tmp;
                }
            }
        }
  }

2、直接选择排序

思路

对于n次循环,每一次循环都把最小的数,交换到最前面的位置

图解

直接选择排序

代码实现

  public static void selectionSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    for(int i = 0; i < arr.length - 1; i++) {
      // 默认认为第一个数为最小的index
      int minIndex = i;
      for(int j = i + 1; j < arr.length; j++) {
        if (arr[minIndex] > arr[j]) {
          // 比较更新最新的index
          minIndex = j;
        }
      }
      // 不相同就交换
      if (minIndex != i) {
        int tmp = arr[minIndex];
        arr[minIndex] = arr[i];
        arr[i] = tmp;
      }
    }
  }

3、直接插入排序

思路

从0开始,逐步从0~arr.length的区域插入一个数,使得原来的数组有序

图解

直接插入排序

代码实现

  public static void insertSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    for(int i = 1; i < arr.length; i++) {
      // 每次子循环中,j代表当前有序数组中,最大的index
      // 因此插入一个数,都要与最大的index,比较交换,直至这个数放在了正确的位置
      for(int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
        int tmp = arr[j + 1];
        arr[j + 1] = arr[j];
        arr[j] = tmp;
      }
    }
  }

4、希尔排序

希尔排序也是一种插入排序,是改进后插入排序,也称为缩小增量排序

思路

1) 对数组,按一定的增量gap分组
2)分别对分组进行直接插入排序
3)直至增量gap减少至0,整个排序完成

图解

希尔排序

代码实现

  public static void shellSort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    for (int gap = arr.length / 2; gap > 0; gap /= 2) {
      // 开始对每个分组进行直接插入排序
      for(int i = gap; i < arr.length; i++) {
        int j = i;
        // 从gap元素开始,逐个对其所在组进行直接插入排序
        while(j - gap >= 0 && arr[j] < arr[j - gap]) {
          int tmp = arr[j - gap];
          arr[j - gap] = arr[j];
          arr[j] = tmp;
          j -= gap;
        }
      }
    }
  }

5、桶排序-计数排序,基数排序

计数排序

思路

1)例如:在0~99的范围内,我们划分了100个桶,并且对桶进行编号
2)在遍历过程中,把每个数放在对应的桶里,那么一次遍历后,每个桶就各自装有其范围的数了,因此时间复杂度只要O(N)
3)最后遍历桶,“倒出”里面装有的数字

图解

计数排序

代码实现

  /// 只考虑>0的情况
  public static void bucketSort(int arr[]) {
    int max = Integer.MIN_VALUE;
    for (int i = 0; i < arr.length; i++) {
      max = Math.max(max, arr[i]);
    }
    // 准备桶,确保桶可以装完所有数据
    // 这样bucket[num]就代表num出现的次数
    int[] bucket = new int[max + 1];
    for(int i = 0; i < arr.length; i++) {
      bucket[arr[i]]++;
    }
    int i = 0;
    // 把桶里面的数据一次倒出来
    for (int j = 0; j < bucket.length; j++) {
        while (bucket[j] > 0) {
            arr[i++] = j;
            bucket[j]--;
        }
    }
  }

基数排序

思路

1)将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。
2)然后,从最低位开始,依次进行一次排序。
3)这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列

图解

基数排序

代码实现

  public static void sort(int[] arr) {
    if (arr == null || arr.length < 2) {
      return;
    }
    // 求最大数,获得数组中最大的位数
    int max = Integer.MIN_VALUE;
    for(int i = 0; i < arr.length; i++) {
      max = Math.max(arr[i], max);
    }
    int maxbits = 0;
    while(max != 0) {
      max /= 10;
      maxbits++;
    }
    radixSort1(arr, maxbits);
  }

  public static void radixSort1(int[] arr, int maxbits) {
    int max = 1;
    int n = 1;
    while(n != maxbits) {
      max *= 10;
      n++;
    }
    n = 1;
    // 一个二维数组[i][j],i表示位数,j是其对应的个数
    int[][] bucket = new int[10][arr.length];
    // 用于保存每个位数的在bucket数组中的个数
    int[] count = new int[10];
    while(n <= max) {
      for(int i = 0; i < arr.length; i++) {
        // 取得n位的位数,例如n=1,取个位数,n=2,取十位数
        int digit = (arr[i] / n) % 10;
        // 放进对应的桶里
        bucket[digit][count[digit]] = arr[i];
        // 该位数的计数+1
        count[digit]++;
      }
      int k = 0;
      for(int i = 0; i < bucket.length; i++) {
        // 表示这个桶里有数据
        if(count[i] != 0) {
          // 全部倒出来
          for(int j = 0; j < count[i]; j++) {
            arr[k++] = bucket[i][j];
          }
        }
        // 归零
        count[i] = 0;
      }
      n *= 10;
    }
  }

桶排序的扩展

相邻最大差值问题,详文见
https://www.jianshu.com/p/e507609ba606

6、堆排序

堆排序需要了解堆的概念,构建堆,调整堆等概念,因此独立写了一份blog。地址如下:
https://www.jianshu.com/p/6513de30c887

7、快速排序

同样地,我也单独写了一篇blog,文中还提到了快排的优化。地址如下:
https://www.jianshu.com/p/9494a3ba1555

8、归并算法

也是单独写了一篇blog,文中提到了归并排序的两个延伸算法问题。地址如下:
https://www.jianshu.com/p/bf854d8160e9

总结

最后对时间复杂度,空间复杂度,稳定性作一个总结

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

推荐阅读更多精彩内容

  • 八大排序法【内部排序】:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序 【插入排序】...
    miyakee阅读 317评论 0 0
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,732评论 0 15
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,188评论 0 52
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    闲云清烟阅读 758评论 0 6
  • 来自Evernote 执行长的岁末祝福:新年新展望,迎接高效2016 作者: Chris O'Neill 发布日期...
    聪聪阅读 917评论 0 0