• 算法怎么就这么难---归并排序和快速排序


    最近学了几天基础的数据结构的知识,越学越为自己的智商捉急了,再看看好多大牛的一些关于算法的博客,真心觉得差距是这么这么大。好了,废话不多少了,接下来我简要讲述一下两个基本的排序:归并排序和快速排序:

    1. 归并排序

    归并排序的原理:归并排序是将一个集合分成两部分:part1和part2,分别对part1和part2进行排序(使用递归法,直到子集合的大小为1,则停止将集合拆分,此时因为子集合中只有一个元素,所以,这个子集合也就相当于已经拍好了顺序),最后将这两部分排好顺序的集合合并为一。

    在编写代码的时候有几个注意点:

    1. 如何将集合分成两部分,各大小都为多少?

      集合的第一部分为list.length/2;集合的第二部分为list.length-list.length/2;

    2. 集合的递归调用什么时候停止?

      当子集合的大小为1时,则停止对集合划分,故在方法的一开始应该加上一个判断

      If(list.length > 1){

      };

    代码实现:

    上段代码的merge方法的作用是将两个集合合并为一个并返回。

    代码实现:

    private static int[] merge(int[] list1, int[] list2){

            int[] temp = new int[list1.length + list2.length];

            int currentPosition1 = 0; //遍历list1时使用的下标变量

            int currentPosition2 = 0; //遍历list2时使用的下标变量

            int currentPositionTemp = 0; //合并两个list时使用的下标变量

     

            //将两个集合中的元素copy到临时变量中

    while(currentPosition1 < list1.length && currentPosition2 < list2.length){             if(list1[currentPosition1] < list2[currentPosition2]){ //将小的元素放到前面。

                    temp[currentPositionTemp++] = list1[currentPosition1++];

                }else

                {

                    temp[currentPositionTemp++] = list2[currentPosition2++];

                }

            }

            //运行到此处时,list1list2中的至少其中一个list已经全部复制到临时集合中,但有可能list1中元素的数量小于list2中元素

    //的数量,因此,需要将list1或者list2中的剩余的数据复制到临时集合中。

            while(currentPosition1 < list1.length){

                temp[currentPositionTemp++] = list1[currentPosition1++];

            }

            while(currentPosition2 < list2.length){

                temp[currentPositionTemp++] = list2[currentPosition2++];

            }

            return temp;

        }

     

    测试代码:

    public static void main(String[] args) {

            // TODO Auto-generated method stub

            int[] list = {1,29,1,2,90,1,0};

            mergeSort(list);

            for(int temp : list){

                System.out.print(temp + " ");

            }

            System.out.println();

        }

    运行结果:

     

     

    1. 快速排序

      快速排序的原理:快速排序在数组中选择一个称为主元(pivot)的元素将数组分成两个部分,使得第一部分的所有元素小于或等于主元(pivot),而第二部分的所有元素均大于主元(pivot)。然后对第一部分递归得应用快速排序算法,然后对第二部分递归得应用快速排序算法。

      Pivot的英文意思为中心点,所以,快速排序可以理解为找中心点,然后根据中心点,将数组分成两部分,一部分小于或等于中心点,另一部分大于中心点,然后按照此方法对两个部分分别执行,最后就将数组排好了顺序。

      为了简单起见,接下来我的代码实现中,将数组的第一个元素作为中心点(pivot)。

    代码如下:

    说明:此段代码的功能是根据集合的第一个元素作为中心点(pivot)将集合分成两个部分,返回中间点pivot的下标

    private static int partition(int[] list, int first, int last){

    //参数firstlast用于指定,将集合的哪一段按照pivot分成两部分。

            int pivot = list[first]; //取第一个元素作为集合的中心点(pivot)

            int low = first + 1;

            int high = last;

            

            while(high > low){

    //找到从前向后数第一个大于pivot的元素,然后找到从后向前数第一个小于pivot的元素,将他们两个互换

                while(low <= high && list[low] <= pivot)

                    low++;

                

                while(low <= high && list[high] > pivot){

                    high--;

                }

                if(high > low){

                    int temp = list[high];

                    list[high] = list[low];

                    list[low] = temp;

                }

            }

    //经过上面一个循环之后,下标小于low的元素均小于pivot,小标大于high的元素均大于pivot

     

            //high的下标从后向前遍历,直到找到当前下标的值小于等于pivot为止

            while(high > first && list[high] >= pivot){

                high--;

            }

            

            if(pivot > list[high]){//if成立,表示pivot的值不是集合中最小的值,此时将pivot的值放到list[high]的位置上

                list[first] = list[high];

                list[high] = pivot;

                return high;

            }else{ //此种情况表示,pivot为集合中最小的元素,因此,pivot值的小标也就是first

                return first;

            }

        }

    quicksort()代码如下:

    private static void quickSort(int[] list, int first, int last){

            if(last > first){

                int pivotIndex = partition(list,first,last);

                quickSort(list,first,pivotIndex -1);

                quickSort(list,pivotIndex+1,last);

            }

        }

    此时,定义一个只有一个集合作为参数的公共方法:

    public static void quickSort(int[] list){

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

        }

     

     

    测试代码:

    public static void main(String[] args) {

            // TODO Auto-generated method stub

            int[] list = {12,3,2,1,5,2};

            quickSort(list);

            for(int temp : list){

                System.out.print(temp + " ");

            }

            System.out.println();

        }

     

    运行结果:

  • 相关阅读:
    seajs加载angularjs
    seajs加载jquery提示$ is not a function
    java 动态代理
    C#第三章--对象和类
    Android笔记--两种双击退出程序的方法
    Android--Volley基本用法及自定义
    Win10专业版只要12.99元?应用商店Bug福利也算数
    新人报道
    排序

  • 原文地址:https://www.cnblogs.com/inghzhang/p/3890901.html
Copyright © 2020-2023  润新知