排序算法

若如初见. 提交于 2020-01-08 21:19:53

冒泡排序

public class BubbleSort {
    //最简洁的冒泡排序写法
    //每次比较相邻的两个元素,如果后方元素比前方元素小,则进行交换
    //每次循环确定一个最大的的元素,放在最后一位

    //平均时间复杂度     N²
    //空间复杂度         1
    //稳定性            稳定
    public static void main(String[] args) {
        int[] number = {233, 666, 1, 6, 648, 328, 128, 999};

        //冒泡排序算法,由小到大排序
        for (int i = 0; i < number.length - 1; i++)
            for (int j = 0; j < number.length - 1 - i; j++)
                if (number[j] > number[j + 1]) {
                    int temp = number[j];
                    number[j] = number[j + 1];
                    number[j + 1] = temp;
                }

        for (int array : number)
            System.out.print(array + " ");
    }
}

选择排序

public class SelectionSort {

    //选择排序
    //不同于冒泡排序进行两两比较元素,然后交换!
    //每次只找出最小数所在数组的索引,然后将其放在第一位
    //每次比较只交换一次

    //平均时间复杂度         N²
    //空间复杂度             1
    //稳定性               不稳定

    public static void main(String[] args) {
        int[] array = {233, 666, 1, 6, 648, 328, 128, 999};

        for (int i = 0; i < array.length - 1; i++) {
            //最小数在数组的索引
            int minIndex = i;
            for (int j = i; j < array.length; j++)
                if (array[j] < array[minIndex])
                    minIndex = j;

            //若minIndex值有变化,则进行交换,使得数组头的元素为最小的
            if (minIndex != i) {
                int temp = array[i];
                array[i] = array[minIndex];
                array[minIndex] = temp;
            }
        }

        for (int sort : array)
            System.out.print(sort + " ");
    }
}

快速排序

public class Quicksort {
    //快速排序
    //将数组中的一个数当做基准数,然后从左右两边进行检索,检索到了则进行交换
    //(如果将最左边的当做基准数,则先从右边检索,再从左边检索,反之亦然)
                             //传入的数组 最左边的索引,最右边的索引
    public static void quickSort(int[] array,int left,int right){
        //如果左边的索引比右边大,则是不合法的,必须结束该方法
        //right可以大于left,可以等于left,但万万不能小于left!
        if (left>right)
            return;

        //定义一个基准数,用以比较
        int base = array[left];

        //保存左右索引
        int i = left;
        int j = right;

        //无法确定循环次数,所以选择while循环
        //当 左右两个索引,同时指向一个元素时,停止循环,然后交换索引元素和 i or j指向的元素的值
        while (i != j){
            //已选择最左边的元素做基准数,则必须先从最右边开始找小于索引值的
            while (array[j] >= base && i < j){
                //进入循环的原因是没找到,所以索引向左移动
                j--;
            }//出循环则意味着找到了

            //右边的找到了,再从左边开始向右找大于基准数的
            while (array[i] <= base && i < j){
                i++;
            }

            //如果程序走到这里,这已经找到了这两个数,进行交换
            int temp = array[i];
            array[i] = array[j];
            array[j] = temp;
            //交换完成
        }

        //如果跳出了这个循环,那么 i 和 j 的值一定相等了,则将 i or j 所指的元素与 基准数进行交换
        //只是交换了索引所指向的值,但是索引本身并没有变化!
        array[left] = array[i];
        array[i] = base;

        //进行递归,先排列基准数左侧的元素
        quickSort(array,left,i-1);

        //再排列右边的元素
        quickSort(array,j+1,right);
    }

    public static void main(String[] args) {
        int[] array = {23,6,99,1,52,88,34,999,666};

        quickSort(array,0,array.length-1);

        for (int a:array)
            System.out.print(a+" ");
    }
}

归并排序

public class MyMegreSort {
    //归并排序
    public static void sort(int[] array, int left, int right) {
        //求中间元素的索引,int型会自动去除小数部分
        if (left < right) {
            int mid = (left + right) / 2;
            //对左边的采用归并排序,使得左边有序
            sort(array, left, mid);
            //对右边的采用归并排序,使得右边有序
            sort(array, mid + 1, right);

            //前两个函数通过不断的递归,让分界线左边的子队列变得有序,再让分界线右边的子队列变得有序
            //最后将两个有序的子队列进行一次普通的比较久可以
            //mid的值动态变化,一定是(left+right)/2的值
            megre(array, left, right, mid);
        }

    }

    //合并两个子序列的自定义函数
    //                          传入的数组  最左索引 最右索引 分界线索引
    public static void megre(int[] array, int left, int right, int mid) {
        //对于已经分好的两个数组,设定两个指针,将这两个子序列当做队列一样处理
        //每次比较后,移动指针

        //创建一个暂存数组
        //最左边的数组长度是right,但是有右边的数组传进来,rigth-left+1才能算出右边的长度
        int[] temp = new int[right - left + 1];

        //左队列指针
        int i = left;

        //右队列指针
        int j = mid + 1;

        //指向暂存数组的指针
        int k = 0;

        //开始实验吧
        while (i <= mid && j <= right) {
            if (array[i] < array[j])
                temp[k++] = array[i++];
            else
                temp[k++] = array[j++];
        }

        //走出这个while循环,一定有一个子队列所有的元素都已放进temp数组,而另一个子队列还有残余
        //但不知道是哪个子队列,所以对两边都执行一次

        //左
        while (i <= mid) {
            temp[k++] = array[i++];
        }

        //右
        while (j <= right) {
            temp[k++] = array[j++];
        }

        //此时元素都已完美的按照从小到大放入了temp数组,使用temp数组覆盖原数组
        //最左边的元素放入array中直接从索引0 开始,但是会有右边的数组放进来,如果从0开始就破坏了以前所排序的
        for (int x = 0; x < temp.length; x++)
            array[x + left] = temp[x];

    }


    public static void main(String[] args) {
        int[] array = {9, 2, 6, 3, 5, 7};
        sort(array, 0, array.length - 1);

        for (int a : array)
            System.out.print(a + " ");
    }
}

堆排序

public class MyHeapSort {
    //公式   带入第i个节点
    //parent = (i-1)/2
    //c1 = 2i+1
    //c2 = 2i+2
    public static void main(String[] args) {
        int[] array = {23, 9, 85, 75, 32, 99, 574, 21, 23};
        //对顶节点进行一次heapify所希望得到的结果
        //85 9 23 75 32

        for (int maxIndex = array.length - 1; maxIndex >= 0; maxIndex--) {
            //求倒数第一个父节点
            int parent = (maxIndex - 1) / 2;

            for (int i = parent; i >= 0; i--) {
                heapifyTest(array, i, maxIndex);
            }

            //574 75 99 23 32 23 85 21 9

            int temp = array[0];
            array[0] = array[maxIndex];
            array[maxIndex] = temp;

        }

        for (int i : array)
            System.out.print(i + " ");
    }

    //heapify
    public static void heapifyTest(int[] array, int parent, int maxIndex) {

        //max变量存放最大值的索引,假设parent节点的值最大,将索引保存至max
        //parent = (length-1)/2;
        int max = parent;

        //利用公式算出左右孩子节点的索引值
        int leftChild = 2 * parent + 1;
        int rightChild = 2 * parent + 2;

        if (leftChild <= maxIndex && array[leftChild] > array[max])
            max = leftChild;

        if (rightChild <= maxIndex && array[rightChild] > array[max])
            max = rightChild;

        //如果max所代表的的索引值和parent不一样了,才会进行交换
        if (max != parent) {
            int temp = array[parent];
            array[parent] = array[max];
            array[max] = temp;
        }
    }
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!