算法之排序算法

排序算法小结

最近没有工作,闲来无事看看算法,从排序算法开始

  • 选择排序
    • 冒泡排序法
    • 快速排序法
  • 插入排序
    • 直接选择排序法
    • 堆排序
  • 其它排序
    • 直接插入排序法
    • 希尔排序法
    • 归并排序法

    冒泡排序

    将数组遍历,第一个数与第二个数比较,把较小的数拿出来,再与第三个数比较,把最小的数拿出来,循环一次,把最小的数拿出来了,第二次循环的次数会减少一次,找到第二小的数,最后排序完成。
    //核心代码

 //缓存元素
        Integer temp;
        for (int i = 0; i < beforeNum.length - 1; i++) {
            for (int j = beforeNum.length - 1; j > i; j--)
                if (beforeNum[j - 1] > beforeNum[j]) {
                    temp = beforeNum[j];
                    beforeNum[j] = beforeNum[j - 1];
                    beforeNum[j - 1] = temp;
                }
        }      

快速排序

设定一个初始值s,两个指针i,j分别指向第一个位置与最后一个位置,j从后往前找比s小的数,i从前往后找比s大的数,找到之后,i,j数进行交换,继续,直到ij相遇,将base与i进行交换。自此,左右的数分别比s小或者大,再分别对左右进行排序,可得。
程序实现:1.找到基准值,2.对基准值进行排序(递归调用)

    //快速排序法 ----选定一个初始值s,2个哨兵i(开始位置)j(结束位置)i从前往后遍历,j从后往前遍历(先)
//j找比s小的数,i找比s大的数,交换,如果ij相遇,s与i交换。此时,s左边的数比s小,s右边的数比s大
//对左边与右边的数分别再进行操作
    public static int division(int[] list, int left, int right) {
        //选择一个基准元素值s
        int baseNum = list[left];
        while (left < right) {
            //从数组右端开始找,找比baseNum小的数
            while (left < right && list[right] >= baseNum)
                right--;
            //将j赋值给基准值
            list[left] = list[right];
            //从数组左端开始,找比基准值大的数
            while (left < right && list[left] <= baseNum)
                left++;
            //将left值赋给右边
            list[right] = list[left];
        }
        list[left] = baseNum;
        return left;
    }

    //快速排序
    public static int[] quickSort(int[] startNum, int left, int right) {
        if (left < right) {
            //分割数据
            int i = division(startNum, left, right);
            quickSort(startNum, left, i - 1);
            quickSort(startNum, i + 1, right);
        }
        return startNum;
    }

直接选择排序

选定一个初始值,将初始值与后面所有数进行比较,找到最小值,交换,在除最小值的数里面找最小值,放到第二位,以此类推。程序实现思路是遍历数组,找到下标最小值,进行数据交换。

for (int i = 0; i < list.length - 1; i++) {
            //假设下标值最小
            int tempIndex = i;
            for (int j = i + 1; j < list.length - 1; j++) {
                if (list[tempIndex] > list[j]) {
                    tempIndex = j;
                }
            }
            //数据交换
            int temData = list[tempIndex];
            list[tempIndex] = list[i];
            list[i] = temData;

        }

堆排序
堆排序需要用到二叉树构建大根堆(父节点比左右孩子都要大),《算法之排序算法》

从根结点3开始,不用交换,左结点2与5交换,交换后再将5与3交换,交换后再将3与4交换,请自行脑补。。。。 每次构建后会对二叉树进行破坏,所以需要重新构建。

  //堆排序
    //调整堆方法
    public static void heapAdjust(int[] list, int parent, int length) {
        //temp保存当前父节点
        int temp = list[parent];

        //得到左孩子(这可是二叉树的定义,大家看图也可知道)
        int child = 2 * parent + 1;

        while (child < length) {
            //如果parent有右孩子,则要判断左孩子是否小于右孩子
            if (child + 1 < length && list[child] < list[child + 1])
                child++;

            //父亲节点大于子节点,就不用做交换
            if (temp >= list[child])
                break;

            //将较大子节点的值赋给父亲节点
            list[parent] = list[child];

            //然后将子节点做为父亲节点,已防止是否破坏根堆时重新构造
            parent = child;

            //找到该父亲节点较小的左孩子节点
            child = 2 * parent + 1;
        }
        //最后将temp值赋给较大的子节点,以形成两值交换
        list[parent] = temp;
    }

    //堆排序算法
    public static int[] heapSort(int[] list) {
        //list.Count/2-1:就是堆中父节点的个数
        for (int i = list.length / 2 - 1; i >= 0; i--) {
            heapAdjust(list, i, list.length);
        }

        //最后输出堆元素
        for (int i = list.length - 1; i > 0; i--) {
            //堆顶与当前堆的第i个元素进行值对调
            int temp = list[0];
            list[0] = list[i];
            list[i] = temp;

            //因为两值交换,可能破坏根堆,所以必须重新构造
            heapAdjust(list, 0, i);
        }
        return list;
    }

直接插入法排序(类似玩牌后理牌)

从无序数列中取出一个数,再取出一个数,对比插入到有序数列前面或者后面,每次取出一个数,进行插入。

  //无序序列
        for (int i = 1; i < list.length; i++) {
            int temp = list[i];
            int j;
            for (j = i - 1; j < i && temp < list[j]; j--) {
                list[j + 1] = list[j];
            }
            list[j + 1] = temp;
        }

希尔排序是对插入排序的补充

《算法之排序算法》

归并排序,将所有的数进行拆分到原子级别,再对原子级别的数亮亮合并。

《算法之排序算法》
ps:由于自身实力的限制,后面几种排序有的没有写例子,感觉不怎么好理解,只能后面再来研究了。可以查看我的参考博客,感觉这个大哥写的东西很好,推荐。另附上我的代码地址(有很多不足还请指教)。https://gitee.com/zhoujie1/studyTest.git

参考博客

1.https://www.cnblogs.com/huangxincheng/archive/2011/11/14/2249046.html
2.https://www.cnblogs.com/huangxincheng/archive/2011/11/16/2251196.html
3.https://www.cnblogs.com/huangxincheng/archive/2011/11/20/2255695.html

点赞