排序算法(Java)

冒泡排序

    public int[] bubble(int[] ary) {
        for (int i = 0; i < ary.length; i++) {
            // 每次确保ary[i]是最小的
            for (int j = i + 1; j < ary.length; j++) {
                if (ary[i] > ary[j]) {
                    int temp = ary[j];
                    ary[j] = ary[i];
                    ary[i] = temp;
                }
            }
        }
        return ary;
    }

插入排序

    public static int[] insert(int[] ary) {
        for (int i = 1; i < ary.length; i++) {
            // key就是一个临界点(哨兵),前面是已经排好序的,后面是未排序的
            int key = ary[i], j;
            // 用key和他前面的值依次比较,发现比该值大就让其后移一位
            for (j = i - 1; j >= 0 && ary[j] > key; j--) {
                ary[j + 1] = ary[j];
            }
            // 走到这里说明key>ary[j],因为之前j是已经-1啦,所以在此+1
            ary[j + 1] = key;
        }
        return ary;
    }

快速排序

这里写图片描述

package common.algorithm.sort;
import java.util.Arrays;
/**
 * 该方法的基本思想是:<br/>
 * 1.先从数列中取出一个数作为基准数。<br/>
 * 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。<br/>
 * 3.再对左右区间重复第二步,直到各区间只有一个数。<br/>
 * 复杂度O(N*logN)
 * @author vv
 * @since 2017/9/4.
 */
public class QuickSort {

    /**
     * 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小
     * 然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
     * @param ary
     */
    public int[] sort(int[] ary) {
        quickSort(ary, 0, ary.length - 1);
        return ary;
    }

    private void quickSort(int[] ary, int low, int high) {
        if (low < high) {
            // 将ary数组进行一分为二
            int middle = partition(ary, low, high);
            // 对低字表进行递归排序
            quickSort(ary, low, middle - 1);
            // 对高字表进行递归排序
            quickSort(ary, middle + 1, high);
        }
    }

    /**
     * 以list的第一个为中轴pivot = ary[low];比pivot小的放在左边,比其大的放在右边,最后返回pivot
     * 
     * @param ary
     * @param low ary的最低位
     * @param high ary的最高位
     * @return
     */
    private int partition(int[] ary, int low, int high) {
        // 数组的第一个作为中轴,低位的值给了pivot,所以ary[low]空出来了
        int pivot = ary[low];
        while (low < high) {
            // 高位比中轴大,则高位索引-1
            while (low < high && ary[high] >= pivot) {
                high--;
            }
            // 高位的值比中轴小,则放到ary[low]上,此后ary[high]又空出来了
            ary[low] = ary[high];

            // 低位比中轴小,则低位索引+1
            while (low < high && ary[low] <= pivot) {
                low++;
            }
            // 比中轴大的记录移到高端
            ary[high] = ary[low];
        }
        // 此处low==high
        ary[low] = pivot;
        // 返回中轴的位置
        return low;
    }

    public static void main(String[] args) {
        QuickSort sorter = new QuickSort();
        System.out.println(Arrays.toString(sorter.sort(new int[] { 2, 5, 2, 1, 7, 3 })));
    }
}

归并排序

package common.algorithm.sort;
import java.util.Arrays;
/**
 * 归并排序是分治法(Divide and Conquer)的一个非常典型的应用<br/>
 * 将已有序的子序列合并,得到完全有序的序列<br/>
 * 两个有序序列段分别为 R[low, mid] 和 R[mid+1, high]<br/>
 * 每次从两个段中取出第一个(最小的)比较,将较小者放入temp中。最后将各段中余下的部分直接复制到temp中。
 *
 * <pre>
 *     {5, 4, 3, 2, 2, 4, 1}
 *     {4,5} {2,3}  {2,2} {4,1}
 *     {2,3,4,5} {1,2,2,4}
 *     {1,2,2,2,3,4,4,5}
 * </pre>
 * 
 * @author vv
 * @since 2016/9/20.
 */
public class MergeSort {

    /**
     * 对数组的begin到end 进行排序
     *
     * @param array 需要排序的数组
     * @param begin 起始位置
     * @param end 终止位置
     */
    public void sort(int[] array, int begin, int end) {
        // 分到最后,i==j说明该组中只有一个元素了
        if (begin < end) {
            int middle = (begin + end) / 2;
            // 递归处理相关的合并事项
            sort(array, begin, middle);// 对第一组排序
            sort(array, middle + 1, end);// 对第二组排序
            merge(array, begin, middle, end);// 合并两组
        }
    }

    /**
     * 对这两组进行合并,从每组中选择最小值进行对比,小的放到temp中
     *
     * @param array 需要排序的原始数组
     * @param low low--middle 为第一组
     * @param middle 分界点
     * @param high middle+1--high 为第二组
     */
    private void merge(int[] array, int low, int middle, int high) {
        int i = low; // i是第一段序列的下标
        int j = middle + 1; // j是第二段序列的下标
        int k = 0; // k是临时存放合并序列的下标
        int[] temp = new int[high - low + 1]; // array2是临时合并序列

        while (i <= middle && j <= high) {
            // 判断第一段和第二段取出的数哪个更小,将其存入合并序列temp,并继续向下扫描
            if (array[i] <= array[j]) {
                temp[k] = array[i];
                i++;
            } else {
                temp[k] = array[j];
                j++;
            }
            k++;
        }

        // 若第一段序列还没扫描完,将其全部复制到合并序列
        while (i <= middle) {
            temp[k] = array[i];
            i++;
            k++;
        }

        // 若第二段序列还没扫描完,将其全部复制到合并序列
        while (j <= high) {
            temp[k] = array[j];
            j++;
            k++;
        }

        // 将合并序列复制到原始序列中
        for (k = 0, i = low; i <= high; i++, k++) {
            array[i] = temp[k];
        }
    }

    public static void main(String[] args) {
        int[] ary = { 5, 4, 3, 2, 2, 4, 1 };
        MergeSort sort = new MergeSort();
        sort.sort(ary, 0, ary.length - 1);
        System.out.println(Arrays.toString(ary));
    }
}

堆排序

package common.algorithm.sort;

import java.util.Arrays;

/**
 * 归并排序是分治法(Divide and Conquer)的一个非常典型的应用<br/>
 * 将已有序的子序列合并,得到完全有序的序列<br/>
 * 两个有序序列段分别为 R[low, mid] 和 R[mid+1, high]<br/>
 * 每次从两个段中取出第一个(最小的)比较,将较小者放入temp中。最后将各段中余下的部分直接复制到temp中。
 *
 * <pre>
 *     {5, 4, 3, 2, 2, 4, 1}
 *     {4,5} {2,3}  {2,2} {4,1}
 *     {2,3,4,5} {1,2,2,4}
 *     {1,2,2,2,3,4,4,5}
 * </pre>
 * 
 * @author vv
 * @since 2016/9/20.
 */
public class MergeSort {

    /**
     * 对数组的begin到end 进行排序
     *
     * @param array 需要排序的数组
     * @param begin 起始位置
     * @param end 终止位置
     */
    public void sort(int[] array, int begin, int end) {
        // 分到最后,i==j说明该组中只有一个元素了
        if (begin < end) {
            int middle = (begin + end) / 2;
            // 递归处理相关的合并事项
            sort(array, begin, middle);// 对第一组排序
            sort(array, middle + 1, end);// 对第二组排序
            merge(array, begin, middle, end);// 合并两组
        }
    }

    /**
     * 对这两组进行合并,从每组中选择最小值进行对比,小的放到temp中
     *
     * @param array 需要排序的原始数组
     * @param low low--middle 为第一组
     * @param middle 分界点
     * @param high middle+1--high 为第二组
     */
    private void merge(int[] array, int low, int middle, int high) {
        int i = low; // i是第一段序列的下标
        int j = middle + 1; // j是第二段序列的下标
        int k = 0; // k是临时存放合并序列的下标
        int[] temp = new int[high - low + 1]; // array2是临时合并序列

        while (i <= middle && j <= high) {
            // 判断第一段和第二段取出的数哪个更小,将其存入合并序列temp,并继续向下扫描
            if (array[i] <= array[j]) {
                temp[k] = array[i];
                i++;
            } else {
                temp[k] = array[j];
                j++;
            }
            k++;
        }

        // 若第一段序列还没扫描完,将其全部复制到合并序列
        while (i <= middle) {
            temp[k] = array[i];
            i++;
            k++;
        }

        // 若第二段序列还没扫描完,将其全部复制到合并序列
        while (j <= high) {
            temp[k] = array[j];
            j++;
            k++;
        }

        // 将合并序列复制到原始序列中
        for (k = 0, i = low; i <= high; i++, k++) {
            array[i] = temp[k];
        }
    }

    public static void main(String[] args) {
        int[] ary = { 5, 4, 3, 2, 2, 4, 1 };
        MergeSort sort = new MergeSort();
        sort.sort(ary, 0, ary.length - 1);
        System.out.println(Arrays.toString(ary));
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值