常见排序算法——七大比较类排序算法(Seven Most Common Sorting Algorithm)

算法 最坏复杂度 平均复杂度 最好复杂度 空间复杂度 稳定性
选择排序(Selection) O( n2 ) O( n2 ) O( n2 ) O(1) 不稳定
插入排序(insertion) O( n2 ) O( n2 ) O( n ) O(1) 稳定
希尔排序(Shell) O( nlog(n)) ~O( n2 ) O( n1.3 ) O( n ) O(1) 不稳定
冒泡排序(Bubble) O( n2 ) O( n2 ) O(n)(用交换flag改进) O(1) 稳定
快速排序(Quick) O( n2 ) O( nlog(n) ) O( nlog(n) ) O(log(n))~O(n) 不稳定
堆排序(heap) O( nlog(n) ) O( nlog(n) ) O( nlog(n) ) O(1) 不稳定
归并排序(merge) O( nlog(n) ) O( nlog(n) ) O( nlog(n) ) O(n) 稳定

Java实现

选择排序

//选择排序:每次遍历找到数组中的最小值,放到剩余数组最前面,以此类推,直到所有元素被排好
        public static void select_sort(int[] arr){
            int len=arr.length;
            long start=System.currentTimeMillis();
            for(int i=0;ifor(int j=i+1;jif(arr[i]>arr[j]){
                        swap(arr,i,j);
                    }
                }
            }
            long end=System.currentTimeMillis();
            System.out.println("选择排序耗时(秒):"+(end-start));
            //toPrint(arr);

        }

插入排序

//插入排序:用新的元素去与已经排序好的元素数组从尾部开始比较,若比对应元素小,则下标继续往前走,直到找到比新元素小的元素,然后将比新元素小的元素后面的全部元素后移,插入新元素。
    public static int[] insert_sort(int[] arr){
            long start=System.currentTimeMillis();
            for(int i=0;iint temp=arr[i];
                for(int j=i;j>0 && arr[j-1]>arr[j];j--){
                    arr[j]=arr[j-1];
                    arr[j-1]=temp;
                }
            }       
            long end=System.currentTimeMillis();
            System.out.println("插入排序耗时(秒):"+(end-start));
            return arr;
            //toPrint(temparr);
        }

希尔排序

    //希尔排序:以arr.length/2为开始间隔,并不断/2缩小间隔的插入排序,最后一次的循环比较e就是插入排序,但是数组的绝大部分元素已经处于相对有序状态。
    public static int[] shell_sort(int arr[]){
            for(int gap=arr.length; gap>0 ; gap/=2){
                for(int i=gap;iint temp=arr[i];
                    for(int j=i;j>=gap && arr[j-gap]>arr[j];j-=gap){
                        arr[j]=arr[j-gap];
                        arr[j-gap]=temp;
                    }
                }
            }
            return arr;
        }

冒泡排序

//冒泡排序:比较相邻两个元素的大小,决定是否交换位置,每次循环可将一个最大值元素一直交换到最后面(或者将最小值一直交换到最前面),以此类推。用一个交换flag作优化可以将最优情况时间复杂度降到O(n),即只比较一轮。
public static void bubble_sort(int[] arr){
        int len=arr.length;
        long start=System.currentTimeMillis();
        boolean swapFlag=true;
        for(int i=0;iif(swapFlag==false)
                break;
            swapFlag=false;
            for(int j=1;jif(arr[j-1]>arr[j]){
                    swap(arr,j-1,j);
                    swapFlag=true;
                }
            }
        }

快速排序

//思路:每一次排序,将首元素(arr[0])交换到这样的位置,即它所在位置往右的所有元素都不小于它,且它所在位置往左的所有元素都不大于它。完成这一步,只需要将首元素不断地从右往左遍历找比它小的,然后从左往右找比它大的,找到即交换位置,一直到从两个方向都再也找不到一个可以交换的元素,一轮排序结束。接着用递归的方式排序剩下的两半。
    public static void quickSort(int[] arr,int start,int end){
            if(start>=end)
                return;

            boolean leftFlag=false,rightFlag=false;

            int pivot=start;
            System.out.println("hehe");
            while(!(leftFlag && rightFlag)){
                leftFlag=true;rightFlag=true;
                //第一轮:第一个元素从右边开始找第一个比它小的元素,与之交换位置
                for(int i=end;i>=start;i--){
                    if(arr[pivot]false;
                    }
                }
                System.out.println("循环");
                for(int i=start;i<=end;i++){
                    if(arr[pivot]false;
                    }
                }
            }

            quickSort(arr, start, pivot-1);
            quickSort(arr, pivot+1,end);

        }

堆排序

具体原理可以参考这里

//堆排序:
    /*
     * 思路:
     *   先将传入的数组做成一个最大二叉堆,然后取出堆顶元素,再调整剩余的二叉堆,重复上述过程。
     */
    public static void heap_sort(int[] arr){
        buildMaxHeap(arr);
        for(int i=arr.length-1;i>=0;i--){
            swap(arr, 0, i);
            maxHeapify(arr, 0, i);
        }
    }

    //从下至上,对所有拥有子结点的根节点进行maxHeapify,保证整个堆的最大堆属性
    private static void buildMaxHeap(int[] arr){
        int iParent=(int) (Math.floor(arr.length/2))-1;
        for(int i=iParent;i>=0;i--){
            maxHeapify(arr, i,arr.length);
        }
    }


    private static void maxHeapify(int[] arr,int index,int heapSize){
        //iMax:最大元素的数组下标
        int iMax=index;

        while(true){
            int iLeft=2*index+1,iRight=2*(index+1);
            //比较当前元素与左子节点值孰大孰小,当然注意判断左子节点是否存在
            if(iLeftarr[iMax])
                iMax=iLeft;

            //比较当前最大元素与右子节点值孰大孰小,当然注意判断右子节点是否存在
            if(iRightarr[iMax])
                iMax=iRight;

            //判断完毕,将最大元素挪移到根节点位置
            if(index!=iMax){
                swap(arr, index, iMax);
                index=iMax;
            }
            else
                break;
        }


    }

归并排序

//思路:将数组不断划分为更小的两个数组的组合(递归),当划分到最小的粒度时,即两个数之间的比较与位置交换,然后不断将两个小的数组融合成大的数组(merge方法)。
    public static void merge_sort(int[] arr,int low,int high){
            if(high>low){
                int pivot=(high+low)/2;
                merge_sort(arr,low,pivot);
                merge_sort(arr,pivot+1,high);
                merge(arr,low,pivot,high);
            }
        }

        private static void merge(int[] arr,int low,int pivot,int high){
            int[] temp=new int[high-low+1];
            int i=low,j=pivot+1;
            int count=0;
            while(i<=pivot && j<=high){
                if(arr[i]>arr[j]){
                    temp[count++]=arr[j];
                    j++;
                }
                else{
                    temp[count++]=arr[i];
                    i++;
                }
            }

            while(i<=pivot){
                temp[count++]=arr[i];
                i++;
            }

            while(j<=high){
                temp[count++]=arr[j];
                j++;
            }
            for(int x=0;x

你可能感兴趣的:(Algorithm,and,Data,Structure)