几种常见的排序算法

冒泡排序

外层循环从1到n-1,内循环从当前外层的元素的下一个位置开始,依次和外层的元素比较,出现逆序就交换,通过与相邻元素的比较和交换来把小的数交换到最前面。
下面展示一些 内联代码片

for(int i=0;i<arr.length-1;i++){//外层循环控制排序趟数
       for(int j=0;j<arr.length-1-i;j++){//内层循环控制每一趟排序多少次
        if(arr[j]>arr[j+1]){
           int temp=arr[j];
           arr[j]=arr[j+1];
           arr[j+1]=temp;
         }
      }
     } 

选择排序

冒泡排序是通过相邻的比较和交换,每次找个最小值。选择排序是:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
下面展示一些 内联代码片

private static void sort(int[] array) {
        int n = array.length;
        for (int i = 0; i < n-1; i++) {
            int min = i;
            for (int j = i+1; j < n; j++) {
                if (array[j] < array[min]){//寻找最小数
                    min = j;                      //将最小数的索引赋值
                 }
            }
            int temp = array[i];
            array[i] = array[min];
            array[min] = temp;

        }
    }

插入排序

通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。可以理解为玩扑克牌时的理牌;

private static void sort(int[] array) {
        int n = array.length;
    /**
    *从第二位数字开始,每一个数字都试图跟它的前一个比较并交换,并重复;直到前一个数字不存在或者比它小或相等时停下来
    **/
        for (int i = 1; i < n; i++) {//从第二个数开始
            int key = array[i];
            int j = i -1;
            while (j >= 0 && array[j]>key) {
                array[j + 1] = array[j];     //交换
                j--;                                //下标向前移动
            }
            array[j+1] = key;
        }
    }

快速排序

通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

private static void sort(int[] array) {
        shuffle(array);
        sort(array, 0, array.length - 1);
    }
    private static void sort(int[] array, int lo, int hi) {
       if(hi<=lo+M) {
        Insert.sort(a,lo,hi);
        return;
        }
        int lt = lo, gt = hi;
        int v = array[lo];
        int i = lo;
        while (i <= gt) {
            if      (array[i]<v) exch(array, lt++, i++);
            else if (array[i]>v) exch(array, i, gt--);
            else              i++;
        }
        // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].
        sort(array, lo, lt-1);
        sort(array, gt+1, hi);
    }

    private static void exch(int[] a, int i, int j) {
        int swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }

    /**
     *打乱数组
     */
    private static void shuffle(int[] array) {
        Random random = new Random(System.currentTimeMillis());
        if (array == null) throw new NullPointerException("argument array is null");
        int n = array.length;
        for (int i = 0; i < n; i++) {
            int r = i + random.nextInt(n-i);     // between i and n-1
            int temp = array[i];
            array[i] = array[r];
            array[r] = temp;
        }
    }
    代码例子:

 1 package test;
 2 
 3 public class s {
 4       public static void main(String[] args) {
 5             int[] arr = { 5,2,4,9,7 };
 6             sort(arr, 0, arr.length - 1);
 7         }
 8         public static void sort(int arr[], int low, int high) {
 9             int l = low;
10             int h = high;
11             int k = arr[low];
12             while (l < h) {
13                 // 从后往前比较
14                 while (l < h && arr[h] >= k ){ // 如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
15                     h--;// h=6
16                 }
17                 if (l < h) {
18                     int temp = arr[h];
19                     arr[h] = arr[l];
20                     arr[l] = temp;
21                     //进行过一次替换后,没必要将替换后的两值再次比较,所以i++直接下一位与k对比
22                     l++;
23                 }
24                 // 从前往后比较
25                 while (l < h && arr[l] <= k) { // 如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
26                     l++;
27                 }
28                 if (l < h) {
29                     int temp = arr[h];
30                     arr[h] = arr[l];
31                     arr[l] = temp;
32                     h--;
33                 }
34                 // 此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
35             }
36             print(arr);
37             System.out.print("l=" + (l + 1) + "h=" + (h + 1) + "k=" + k + "\n");
38             // 递归
39             if (l > low)//先判断l>low再次经行左边排序
40                 sort(arr, low, l - 1);// 左边序列。第一个索引位置到关键值索引-1
41             if (h < high)//左边依次排序执行完递归后,弹栈进行右边排序
42                 sort(arr, l + 1, high);// 右边序列。从关键值索引+1到最后一个
43         }
44         // 打印数组的方法
45         private static void print(int[] arr) {
46             System.out.print("[");
47             for (int i = 0; i < arr.length; i++) {
48                 if (i != (arr.length - 1)) {
49                     System.out.print(arr[i] + ",");
50                 } else {
51                     System.out.print(arr[i] + "]");
52                     System.out.println();
53                 }
54             }
55         }
56 }

堆排序

堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

public static void sort(int[] a){
        int N = a.length;
        int[] keys = new int[N+1];
        //注意,堆的数据结构是从1开始的,0不用
        for (int i = 1; i < keys.length; i++) {
            keys[i] = a[i-1];
        }
//      //构造堆,使得堆是有序的
        for(int k = N/2;k>=1;k--) sink(keys,k,N);
        //排序,相当于毁掉堆
        while(N>1){
            exch(keys,1,N--);
            sink(keys,1,N);
        }
        //重新写回数组
        for (int i = 0; i < a.length; i++) {
            a[i] = keys[i+1];
        }
    }

    private static void sink(int[] a, int k, int N) {
        // TODO Auto-generated method stub
        while(2*k<=N){
            int j = 2*k;
            if (j < N && less(a[j], a[j+1])) j++;
            if (less(a[j], a[k])) break;
            exch(a, k, j);
            k = j;
        }
    }

    private static boolean less(int k, int j) {
        // TODO Auto-generated method stub
        return k < j;
    }

    private static void exch(int[] a, int i, int n) {
        // TODO Auto-generated method stub
        int temp = a[i];
        a[i] = a[n];
        a[n] = temp;
    }
//package test;

public class dui {
    /**
       * 调整为小顶堆(排序后结果为从大到小)
       *
       * @param array是待调整的堆数组
       * @param s是待调整的数组元素的位置
       * @param length是数组的长度
       *
       */
      public static void heapAdjustS(int[] array, int s, int length) {
        int tmp = array[s];
        int child = 2 * s + 1;// 左孩子结点的位置
        System.out.println("待调整结点为:array[" + s + "] = " + tmp);
        while (child < length) {
          // child + 1 是当前调整结点的右孩子
          // 如果有右孩子且小于左孩子,使用右孩子与结点进行比较,否则使用左孩子
          if (child + 1 < length && array[child] > array[child + 1]) {
            child++;
          }
          System.out.println("将与子孩子 array[" + child + "] = " + array[child] + " 进行比较");
          // 如果较小的子孩子比此结点小
          if (array[s] > array[child]) {
            System.out.println("子孩子比其小,交换位置");
            array[s] = array[child];// 把较小的子孩子向上移动,替换当前待调整结点
            s = child;// 待调整结点移动到较小子孩子原来的位置
            array[child] = tmp;
            child = 2 * s + 1;// 继续判断待调整结点是否需要继续调整

            if (child >= length) {
              System.out.println("没有子孩子了,调整结束");
            } else {
              System.out.println("继续与新的子孩子进行比较");
            }
            // continue;
          } else {
            System.out.println("子孩子均比其大,调整结束");
            break;// 当前待调整结点小于它的左右孩子,不需调整,直接退出
          }
        }
      }

      /**
       * 调整为大顶堆(排序后结果为从小到大)
       *
       * @param array是待调整的堆数组
       * @param s是待调整的数组元素的位置
       * @param length是数组的长度
       *
       */
      public static void heapAdjustB(int[] array, int s, int length) {
        int tmp = array[s];
        int child = 2 * s + 1;// 左孩子结点的位置
        System.out.println("待调整结点为:array[" + s + "] = " + tmp);
        while (child < length) {
          // child + 1 是当前调整结点的右孩子
          // 如果有右孩子且大于左孩子,使用右孩子与结点进行比较,否则使用左孩子
          if (child + 1 < length && array[child] < array[child + 1]) {
            child++;
          }
          System.out.println("将与子孩子 array[" + child + "] = " + array[child] + " 进行比较");
          // 如果较大的子孩子比此结点大
          if (array[s] < array[child]) {
            System.out.println("子孩子比其大,交换位置");
            array[s] = array[child];// 把较大的子孩子向上移动,替换当前待调整结点
            s = child;// 待调整结点移动到较大子孩子原来的位置
            array[child] = tmp;
            child = 2 * s + 1;// 继续判断待调整结点是否需要继续调整

            if (child >= length) {
              System.out.println("没有子孩子了,调整结束");
            } else {
              System.out.println("继续与新的子孩子进行比较");
            }
            // continue;
          } else {
            System.out.println("子孩子均比其小,调整结束");
            break;// 当前待调整结点大于它的左右孩子,不需调整,直接退出
          }
        }
      }

      /**
       * 堆排序算法
       *
       * @param array
       * @param inverse true 为倒序排列,false 为正序排列
       */
      public static void heapSort(int[] array, boolean inverse) {
        // 初始堆
        // 最后一个有孩子的结点位置 i = (length - 1) / 2, 以此向上调整各结点使其符合堆
        System.out.println("初始堆开始");
        for (int i = (array.length - 1) / 2; i >= 0; i--) {
          if (inverse) {
            heapAdjustS(array, i, array.length);
          } else {
            heapAdjustB(array, i, array.length);
          }
        }
        System.out.println("初始堆结束");
        for (int i = array.length - 1; i > 0; i--) {
          // 交换堆顶元素H[0]和堆中最后一个元素
          int tmp = array[i];
          array[i] = array[0];
          array[0] = tmp;
          // 每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整
          if (inverse) {
            heapAdjustS(array, 0, i);
          } else {
            heapAdjustB(array, 0, i);
          }
        }
      }

      public static void main(String[] args) {
        int[] array = { 49, 38, 65, 97, 76, 13, 27, 49 };
        heapSort(array, false);
        for (int i : array) {
          System.out.print(i + " ");
        }
      }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值