zoukankan      html  css  js  c++  java
  • 八大常见内排序java实现

      虽然排序算法烂大街了,但是哥依然用java实现了一遍,只为自己练练手,后面可以时不时的回头看看。。。仅此而已,各位可以提意见,莫喷!!

    一、冒泡排序

      基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换

     1 /**
     2      * 冒泡排序
     3      * @param data    要排序的数组
     4      * @param reverse 从大到小(false)还是从小到大(ture)
     5      */
     6     public static void sort(int[] data, boolean reverse) {
     7         if (data.length == 1) {
     8             return;
     9         }
    10         for (int i = 0; i < data.length - 1; i++) {
    11             int tmp = 0;
    12             for (int j = 0; j < data.length - i - 1; j++) {
    13                 if (reverse) {  //从小到大(ture)
    14                     if (data[j] >= data[j+1]) {
    15                         tmp = data[j];
    16                         data[j] = data[j +1 ];
    17                         data[j+1] = tmp;
    18                     }
    19                 } else {    //从大到小(false)
    20                     if (data[j] <= data[j+1]) {
    21                         tmp = data[j+1];
    22                         data[j+1] = data[j];
    23                         data[j] = tmp;
    24                     }
    25                 }
    26             }
    27         }
    28     }
    View Code

    二、堆排序

      基本思想:堆排序是一种树形选择排序,是对直接选择排序的有效改进。

      堆的定义如下:具有n个元素的序列(h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)时称之为堆。在这里只讨论满足前者条件的堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项(大顶堆)。完全二叉树可以很直观地表示堆的结构。堆顶为根,其它为左子树、右子树。初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储序,使之成为一个堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数  

     1 /**
     2      * 堆排序
     3      * @param data    要排序的数组
     4      * @param reverse 从大到小(false)还是从小到大(ture)
     5      */
     6     public static void sort(int[] data, boolean reverse) {
     7         if (data.length == 1) {
     8             return;
     9         }
    10         for (int i = 0; i < data.length; i++) {
    11             //建堆
    12             buildHeap(data, 0, data.length -1 - i, reverse);
    13             int tmp = data[0];
    14             data[0] = data[data.length - 1 - i];
    15             data[data.length - 1 - i] = tmp;
    16         }
    17     }
    18 
    19     /**
    20      * 将指定开始和结束段的数据建堆
    21      * @param data
    22      * @param beginIndex
    23      * @param endIndex
    24      * @param reverse
    25      */
    26     public static void buildHeap(int[] data, int beginIndex, int endIndex, boolean reverse) {
    27         if (beginIndex >= endIndex) {
    28             return;
    29         }
    30         for (int i = (endIndex + beginIndex - 1) / 2; i >= beginIndex; i--) {
    31             int cur = i;
    32             if (reverse) {   //大顶堆,用来从小到大排序
    33                 //发生交换之后需要检查孙子节点,重孙子节点...
    34                 while (2 * cur + 1 <= endIndex) {
    35                     int biggerChildIndex = 2 * cur + 1;
    36                     if (biggerChildIndex + 1 <= endIndex) {
    37                         if (data[biggerChildIndex] < data[biggerChildIndex + 1]) {
    38                             biggerChildIndex = biggerChildIndex + 1;
    39                         }
    40                     }
    41                     //找到最大子节点,如果比当前节点大,就交换
    42                     if (data[i] < data[biggerChildIndex]) {
    43                         int tmp = data[i];
    44                         data[i] = data[biggerChildIndex];
    45                         data[biggerChildIndex] = tmp;
    46                         //准备检查孙子节点
    47                         cur = biggerChildIndex;
    48                     } else {
    49                         break;
    50                     }
    51                 }
    52             } else {    //小顶堆,用来从大到小排序
    53                 //发生交换之后需要检查孙子节点,重孙子节点...
    54                 while (2 * cur + 1 <= endIndex) {
    55                     int samllerChildIndex = 2 * i + 1;
    56                     if (samllerChildIndex + 1 <= endIndex) {
    57                         if (data[samllerChildIndex] > data[samllerChildIndex + 1]) {
    58                             samllerChildIndex = samllerChildIndex + 1;
    59                         }
    60                     }
    61                     //找到最小子节点,如果比当前节点小,就交换
    62                     if (data[i] > data[samllerChildIndex]) {
    63                         int tmp = data[i];
    64                         data[i] = data[samllerChildIndex];
    65                         data[samllerChildIndex] = tmp;
    66                         cur = samllerChildIndex;
    67                     } else {
    68                         break;
    69                     }
    70                 }
    71             }
    72         }
    73     }
    View Code

    三、直接插入排序

      基本思想:在要排序的一组数中,假设前面(n-1)[n>=2]个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

     1 /**
     2      *  插入排序
     3      * @param data  要排序的数组
     4      * @param reverse 从大到小(false)还是从小到大(ture)
     5      */
     6     public static void sort(int[] data, boolean reverse) {
     7         if (data.length == 1) {
     8             return;
     9         }
    10         int tmp = 0;
    11         for (int i = 1; i < data.length; i++) {
    12             tmp = data[i];
    13             int n = i - 1;
    14             for (; n >= 0; n--) {
    15                 if (reverse) {   //从小到大排序
    16                     if (data[n] >= tmp) {
    17                         data[n + 1] = data[n];  //将大于当前值的数后移一个位置
    18                     } else {
    19                         break;
    20                     }
    21                 } else {    //从大到小排序
    22                     if (data[n] <= tmp) {
    23                         data[n + 1] = data[n];  //将小于当前值的数后移一个位置
    24                     } else {
    25                         break;
    26                     }
    27                 }
    28             }
    29             data[n+1] = tmp;
    30         }
    31     }
    View Code

    四、归并排序

      基本思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。 

     1  /**
     2      * 归并排序
     3      * @param data    要排序的数组
     4      * @param reverse 从大到小(false)还是从小到大(ture)
     5      */
     6     public static void sort(int[] data, int left, int right, boolean reverse) {
     7         if (left >= right) {
     8             return;
     9         }
    10         int mid = (left + right) / 2;
    11         sort(data, left, mid, reverse);
    12         sort(data, mid + 1, right, reverse);
    13         merge(data, left, mid, right, reverse);
    14     }
    15 
    16     /**
    17      * 合并已排序好的两段
    18      * @param data
    19      * @param left
    20      * @param mid
    21      * @param right
    22      * @param reverse
    23      */
    24     public static void merge(int[] data, int left, int mid, int right, boolean reverse) {
    25         int[] tmp = new int[right - left + 1];
    26         int i = left;
    27         int j = mid + 1;
    28         int n = 0;
    29         while (i <= mid && j <= right) {
    30             if (reverse) {  //从小到大
    31                 if (data[i] <= data[j]) {
    32                     tmp[n++] = data[i++];
    33                 } else {
    34                     tmp[n++] = data[j++];
    35                 }
    36             } else {    //从大到小
    37                 if (data[i] <= data[j]) {
    38                     tmp[n++] = data[j++];
    39                 } else {
    40                     tmp[n++] = data[i++];
    41                 }
    42             }
    43         }
    44         while (i <= mid) {
    45             tmp[n++] = data[i++];
    46         }
    47         while (j <= right) {
    48             tmp[n++] = data[j++];
    49         }
    50         for (int k = 0; k < tmp.length; k++) {
    51             data[left + k] = tmp[k];
    52         }
    53     }
    View Code

    五、快递排序

      基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分

     1    /**
     2      * 快速排序
     3      * @param data
     4      * @param left
     5      * @param right
     6      * @param reverse 从大到小(false)还是从小到大(ture)
     7      */
     8     public static void sort(int[] data, int left, int right, boolean reverse) {
     9         if (left >= right) {
    10             return;
    11         }
    12         int index = getIndex(data, left, right, reverse);
    13         sort(data, left, index - 1, reverse);
    14         sort(data, index + 1, right, reverse);
    15     }
    16 
    17     /**
    18      * 将待排序片段调整顺序,获得"中间数据"的正确索引
    19      * @param data
    20      * @param left
    21      * @param right
    22      * @param reverse 从大到小(false)还是从小到大(ture)
    23      * @return
    24      */
    25     public static int getIndex(int[] data, int left, int right, boolean reverse) {
    26         int cur = data[left];
    27         int i = left;
    28         int j = right;
    29         while (i < j) {
    30             if (reverse) {  //从小到大
    31                 while (data[j] > cur && i < j) {
    32                     --j;
    33                 }
    34                 data[i] = data[j];
    35                 while (data[i] <= cur && i < j) {
    36                     ++i;
    37                 }
    38                 data[j]=data[i];
    39             } else {    //从大到小
    40                 while (data[j] < cur && i < j) {
    41                     --j;
    42                 }
    43                 data[i]=data[j];
    44                 while (data[i] >= cur && i < j) {
    45                     ++i;
    46                 }
    47                 data[j]=data[i];
    48             }
    49         }
    50         data[i] = cur;
    51         return i;
    52     }
    View Code

    六、基数排序

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

     1     /**
     2      * 基数排序
     3      * @param data    要排序的数组
     4      * @param reverse 从大到小(false)还是从小到大(ture)
     5      */
     6     public static void sort(int[] data, boolean reverse) {
     7         if (data.length == 1) {
     8             return;
     9         }
    10         int max = 0;
    11         for (int i = 0; i < data.length; i++) { //找出最大的数据
    12             if (max < data[i]) {
    13                 max = data[i];
    14             }
    15         }
    16         System.out.println("the max number is :" + max);
    17         int radix = 1;
    18         ArrayList<ArrayList<Integer>> numbers = new ArrayList<ArrayList<Integer>>(10);
    19         for (int i = 0; i < 10; i++) {
    20             numbers.add(i, new ArrayList<Integer>());
    21         }
    22         while (max > radix) {
    23             for (int i = 0; i < data.length; i++) {
    24                 int index = (data[i] / radix) % 10;
    25                 ArrayList<Integer> list = numbers.get(index);
    26                 list.add(data[i]);
    27                 numbers.set(index, list);
    28             }
    29             resetOrder(data, numbers, reverse);
    30             radix = radix * 10;
    31         }
    32     }
    33 
    34     /**
    35      * 重新调整数组顺序
    36      * @param data
    37      * @param numbers
    38      * @param reverse 从大到小(false)还是从小到大(ture)
    39      */
    40     public static void resetOrder(int[] data, ArrayList<ArrayList<Integer>> numbers, boolean reverse) {
    41         int n = 0;
    42         if (reverse) {
    43             for (int i = 0; i < numbers.size(); i++) {
    44                 ArrayList<Integer> list = numbers.get(i);
    45                 while(list.size()>0){
    46                     data[n++] = list.get(0);
    47                     list.remove(0);
    48                 }
    49             }
    50         } else {
    51             for (int i = numbers.size() - 1; i >= 0; i--) {
    52                 ArrayList<Integer> list = numbers.get(i);
    53                 while(list.size()>0){
    54                     data[n++] = list.get(0);
    55                     list.remove(0);
    56                 }
    57             }
    58         }
    59     }
    View Code

    七、选择排序

      基本思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

     1     /**
     2      * 选择排序
     3      * @param data  要排序的数组
     4      * @param reverse 从大到小(false)还是从小到大(ture)
     5      */
     6     public static void sort(int[] data, boolean reverse) {
     7         if (data.length == 1) {
     8             return;
     9         }
    10         for(int i=0;i<data.length-1;i++){
    11             int tmp=data[i];    //要初始化
    12             int index = i;      //要初始化
    13             for(int j=i;j<data.length;j++){
    14                 if(reverse) {   //从小到大(ture)
    15                     if (tmp>=data[j]){
    16                         tmp = data[j];  //最小值
    17                         index = j;
    18                     }
    19                 }else {
    20                     if (tmp<=data[j]){
    21                         tmp = data[j];  //最大值
    22                         index = j;
    23                     }
    24                 }
    25             }
    26             data[index] = data[i];
    27             data[i] = tmp;
    28         }
    29     }
    View Code 

    八、希尔排序

       基本思想:算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减到1时,进行直接插入排序后,排序完成。

     1     /**
     2      * 希尔排序
     3      * @param data    要排序的数组
     4      * @param reverse 从大到小(false)还是从小到大(ture)
     5      */
     6     public static void sort(int[] data, boolean reverse) {
     7         if (data.length == 1) {
     8             return;
     9         }
    10         for (int d = data.length / 2; d >= 1; d = d / 2) {  //组大小
    11             for (int k = 0; k < d; k++) {   //多少组
    12                 for (int n = d + k; n < data.length; n = n + d) {   //同一组
    13                     int cur = n;
    14                     while (cur - d >= 0) {  //插入排序
    15                         int tmp = 0;
    16                         if (reverse) {  //小到大(ture)
    17                             if (data[cur] <= data[cur - d]) {
    18                                 tmp = data[cur];
    19                                 data[cur] = data[cur - d];
    20                                 data[cur - d] = tmp;
    21                             }
    22                         } else {         //从大到小(false)
    23                             if (data[cur] >= data[cur - d]) {
    24                                 tmp = data[cur];
    25                                 data[cur] = data[cur - d];
    26                                 data[cur - d] = tmp;
    27                             }
    28                         }
    29                         cur = cur - d;
    30                     }
    31                 }
    32             }
    33         }
    34 
    35     }
    View Code

    相关的资料大伙可以自行寻找,本文就不详细介绍了。。。 都烂大街了。。。

    以下是一些不错的相关文章

    参考:

      1.http://blog.csdn.net/qy1387/article/details/7752973#0-tsina-1-35851-397232819ff9a47a7b7e80a40613cfe1

      2.http://www.cnblogs.com/luxiaoxun/archive/2012/09/01/2666677.html

      3.http://www.cnblogs.com/yefengmeander/archive/2008/12/05/2887903.html

      4.http://blog.jobbole.com/79288/

      5.https://github.com/ztgu/sorting_algorithms_py

    就当自己回顾知识了

      

  • 相关阅读:
    产品分析之核心功能篇
    激励CEO们最好的办法就是鼓励他们不要停止思考
    Javascript的一些经验总结
    微信为什么跟你想要的不一样?
    互联网思维西游记漫画分享
    交互设计与人类行为习惯的一些思考
    说说三四月的app审核中的几个坑
    程序员的玻璃心
    常用网站日志分析软件使用总结
    在你决定从事iOS开发前需要清楚的几个问题
  • 原文地址:https://www.cnblogs.com/lxf20061900/p/5063977.html
Copyright © 2011-2022 走看看