java排序

图片来自网络

一、用泛型实现快排,可以传入不通类型进行排序,比如String数组,Integer数组。

/**
 * 快速排序
 * 
 * @author chx
 *
 */
public class QuickSort {
    /**
     * 数组内数值的交换函数
     * 
     * @param arr
     *            原数组
     * @param leftIndex
     *            左索引
     * @param rightIndex
     *            右索引
     */
    private static <T> void change(T[] arr, int leftIndex, int rightIndex) {
        T temp = arr[leftIndex];
        arr[leftIndex] = arr[rightIndex];
        arr[rightIndex] = temp;
    }

    public static <T> void sort(T[] arr, int left, int right) {
        if (right < left) {
            // 查找区间内,外的返回
            return;
        }
        T flag = arr[left];// 哨兵的值
        int indexLeft = left;// 本轮查找需要的左索引
        int indexRight = right;// 本轮查找需要的右索引

        while (indexLeft != indexRight) {
            // 开始从右向左找,找比哨兵小的值。或者直到遇到左索引
            while (Integer.parseInt(arr[indexRight].toString()) >= Integer.parseInt(flag.toString())
                    && indexLeft < indexRight) {
                indexRight--;
            }
            // 从左向右找,找到比哨兵大的值,或者直到遇到右索引
            while (Integer.parseInt(arr[indexLeft].toString()) <= Integer.parseInt(flag.toString())
                    && indexLeft < indexRight) {
                indexLeft++;
            }
            if (indexLeft < indexRight) {
                // 找到了,交换
                change(arr, indexLeft, indexRight);
            }
        }
        // 此时一遍探索结束,将哨兵和当前的值进行交换,并进行分区探索
        change(arr, left, indexLeft);
        // 右边探索
        sort(arr, indexRight + 1, right);
        // 左边探索
        sort(arr, left, indexLeft - 1);
    }
}

 二、利用Arrays.sort()进行排序

  突然有个同学咨询Arrays.sort用法,正好在此记录。

  1.简介:有的时候不愿意去写排序程序,可以利用java自带的Arrays.sort()方法。

2.使用规则:总结为,基本数据类型直接放,引用数据类型需要利用实现了Comparator<T>的对象辅助排序。

3.具体用法:

package mianshi;

import java.util.Arrays;
import java.util.Comparator;

public class SortTest implements Comparator<SortTest> {
    private int sortValue;

    public int getSortValue() {
        return sortValue;
    }

    public void setSortValue(int sortValue) {
        this.sortValue = sortValue;
    }

    public static void main(String[] args) {
        SortTest[] list = new SortTest[5];

        for (int i = 0; i < list.length; i++) {
            list[i] = new SortTest();
            list[i].setSortValue(i*2);
        }

        Comparator<SortTest> cmp = new SortTest();
        Arrays.sort(list, cmp);

        for (int i = 0; i < list.length; i++) {
            System.out.print(list[i].getSortValue() + " ");
        }
    }

    @Override
    public int compare(SortTest o1, SortTest o2) {
        if (o1.getSortValue() > o2.getSortValue()) {
            return -1;
        }else if(o1.getSortValue() < o2.getSortValue()) {
            return 1;
        }

        return 0;
    }
}

返回值规则:compare是实现对比的方法,正数-大于,0-等于,负数-小于。所以本程序是倒序排序。

tips:感兴趣的可以百度下compare的实现原理、算法选择。有很多需要了解的内容。

三、有关排序算法

//选择排序
public static void xuanZeSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] > arr[j]) {
                    int tmp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tmp;
                }
            }
        }
    }
 /**
     * 插入排序
     *
     * @param
     * @param arr
     * @return
     * @author chx
     * @date 2020/6/5 17:48
     */
    public static void insertSort(int[] arr) {
        //就一个核心思想。从第I个数开始向左找比其大(小)的位置index,期间全体右移。
        for (int i = 1; i < arr.length; i++) {
            int flag = arr[i];
            int j = i;

            while (j > 0 && flag < arr[j - 1]) {
                arr[j] = arr[j - 1];
                j--;
            }

            //此位置要么为0要么为找到的位置,由于一直右移,所以一定替换。
            arr[j] = flag;
        }
    }
/**
     * 希尔排序:真的只是对插入排序做了改善,代码及其相似。
     *
     * @param arr
     */
    public static void shellSort(int[] arr) {
        //增量因子这里可以百度,因子的选择有一定可能会影响效率。
        int step = arr.length / 3 + 1;
        //和插入排序多了一个while循环,当步长为0时表示排序完成。
        while (step > 0) {
            //从[步长位]开始,和所有第[i-步长]及[j-步长]比较,并进行移位。
            for (int i = step; i < arr.length; i++) {
                int flag = arr[i];
                int j = i - step;
                //和所有[j-step]位数值进行比较,
                while (j >= 0 && flag < arr[j]) {
                    //移位
                    arr[j + step] = arr[j];
                    j -= step;
                }

                arr[j + step] = flag;
            }

            step = (int) Math.floor(step / 3);
        }
    }
/**
     * 堆排序-大顶堆排序(升序)
     *
     * @param
     * @param arr
     * @return
     * @author chx
     * @date 2020/6/8 11:18
     */
    private static void bigHeapSort(int[] arr) {
        //将树的结构线性化,按照左子节点坐标=2*i+1,右子节点坐标=2*i+2。其中i表示坐标。
        //所以从最后一个非叶子节点开始(坐标为最大下标/2),自左向右(自右向左)比较其叶子节点和其父节点大小。
        //确保父节点永远比叶子节点大(小顶堆找最小),最终构建好的线性表即为大顶堆(其根节点是最大值)。其根节点要么最大要么最小。
        for (int i = arr.length / 2; i >= 0; i--) {
            changeHeapValue(arr, i, arr.length);
        }

        //创建完堆之后,对堆进行调整,每次调整把最大值放于根节点,并调换最后一个叶子节点和根节点,直到堆里只剩一个数据。
        int length = arr.length;

        for (int i = length - 1; i > 0; i--) {
            //交换根节点和最后一个子节点,这样就相当于把最大值取出来了。
            swap(arr, 0, i);
            //由于换了根节点和最后一个节点,所以重新排序。
            length--;
            changeHeapValue(arr, 0, length);
        }
    }


    /**
     * 交换两个下标的数值
     *
     * @param
     * @param arr       数组
     * @param index     下标A
     * @param swapIndex 下标B
     * @return
     * @author chx
     * @date 2020/6/8 11:41
     */
    private static void swap(int[] arr, int index, int swapIndex) {
        int tmp = arr[index];
        arr[index] = arr[swapIndex];
        arr[swapIndex] = tmp;
    }

    /**
     * 创建大顶堆过程中,比较父节点及其叶子节点的大小,进行改值操作。
     *
     * @param arr
     * @param index
     * @return
     * @author chx
     * @date 2020/6/8 12:07
     */
    private static void changeHeapValue(int[] arr, int index, int lenth) {
        int leftIndex = index * 2 + 1;
        int rightIndex = index * 2 + 2;
        int tmpIndex = index;

        //此处不用arr.length的原因是,后面对堆进行排序时会修改长度。因为最终堆只剩一个的时候就排序完了。
        if (leftIndex < lenth && arr[tmpIndex] < arr[leftIndex]) {
            //左子节点大于其父节点,记录,后面要交换。
            tmpIndex = leftIndex;
        }

        if (rightIndex < lenth && arr[tmpIndex] < arr[rightIndex]) {
            //右子节点大于其父节点,记录,后面进行交换。
            tmpIndex = rightIndex;
        }

        if (tmpIndex != index) {
            // 期间有改动,说明找到需要交换的值了,进行交换。
            swap(arr, index, tmpIndex);
            // 此子节点下继续探索,防止由于子父节点更换,导致原来子节点及其子节点的子节点 排列好的数据已经不符合大顶堆规则。
            changeHeapValue(arr, tmpIndex, lenth);
        }
    }
/**
     * 归并排序之递归实现
     */
    public static void mergeSortRecurrence(int[] arr, int left, int right) {
        //最小单位是两两比较,所以遇到1以下的就直接返回。
        if (left < right) {
            int mid = (left + right) / 2;
            //左边分割
            mergeSortRecurrence(arr, left, mid);
            //右边分割
            mergeSortRecurrence(arr, mid + 1, right);
            //合并排序
            mergeSortMerge(arr, left, mid, right);
        }
    }

    /**
     * 合并分割后的数组,并排序。最终会合为一个排序好的大数组。
     *
     * @param arr
     * @param left
     * @param mid
     * @param right
     */
    private static void mergeSortMerge(int[] arr, int left, int mid, int right) {
        //创建一个临时数组,用左数组的值与右数组的比较,由于左右两边都是有序的,所以才能保证放进临时数组的都是正确的。
        int[] tmp = new int[arr.length];//辅助数组
        int p1 = left, p2 = mid + 1, k = left;//p1、p2是检测指针,k是存放指针

        while (p1 <= mid && p2 <= right) {
            if (arr[p1] <= arr[p2]){
                tmp[k++] = arr[p1++];
            }
            else{
                tmp[k++] = arr[p2++];
            }
        }

        while (p1 <= mid) tmp[k++] = arr[p1++];//如果左边未检测完,直接将后面所有元素加到合并的序列中
        while (p2 <= right) tmp[k++] = arr[p2++];//同上

        //复制回原素组
        for (int i = left; i <= right; i++) {
            arr[i] = tmp[i];
        }
    }

 

posted @ 2019-07-22 11:48  chxLonely  阅读(383)  评论(0编辑  收藏  举报