希尔排序和快速排序

1.希尔排序

又叫sell排序,任何情况下时间复杂度均为O(n^(3/2))即 O(n^1.3~1.5), 只需要一个额外的空间,所以空间复杂度是最佳的。不稳定

选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,
冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。

希尔排序思想:原理有点像直接插入法,但它可以减少数据搬移次数,排序的原则是将数据分成特定间隔的小组,以直接插入法排完小组内的数据后再减少间隔的距离重新分组,再排序,再分再排,最后以所有数据为一个大组,再用直接插入法比较,因为直接插入法就是越有序越快,所以分组每组排序后就让每组数据变得有序,提高了算法的效率,所以sell排序也叫直接插入法的优化。

这里写图片描述

这里写图片描述

package javapaixu;

import java.util.Arrays;

public class Xier {
    public static void sell(int[] array,int gap) {//gap分组
        int tmp = 0;
        int j = 0;
        for(int i = gap;i < array.length;i++) {
            tmp = array[i];
            for(j = i-gap;j >= 0;j -= gap) {
                if(array[j] > tmp) {
                    array[j+gap] = array[j];
                }else {
                    break;
                }
            }
            array[j+gap] = tmp;
        }
    }
        public static void sellSort(int[] array){
             int[] d = {3,1};//分组
             for(int i=0;i<d.length;i++){
                 sell(array,d[i]);//调用比较方法,也就是变态了的直接插入排序法
         }
        }
    public static void main(String[] args) {
        int[] array={101,213,12,98,45,36};
        sellSort(array);
        System.out.println(Arrays.toString(array));

    }

}

运行结果:

[12, 36, 45, 98, 101, 213]

1.快速排序

快速排序就是分割交换的排序方法,是目前公认的最佳排序方法,在最快以及平均情况下,时间复杂度为O(nlogn)。最坏情况就是每次挑中的基准值不是最大就是最小,其时间复杂度为O(n^2);它有跳跃式交换,不稳定,在最差情况下的空间复杂度为O(n),而最佳情况下为O(nlogn)。快速排序法是平均运行时间最快的排序法。

快速排序的思想:它的原理和冒泡排序一样,都是用交换的方式,不过它会现在数据中找一个基准,把小于这个基准的数据放在左边,大于基准的放在右边。再以同样的方式处理两边的数据。

现定义两个下标,low和high分别指向第一个和最后一个,low从前往后走,high从后往前走,一般第一次以第一个元素为基准:

这里写图片描述

把小于这个基准的数据放在左边,大于基准的放在右边:

代码如下:

int tmp = array[low];
        while(low < high) {
            while(low < high && array[high] >= tmp) {
                --high;
            }
             array[low] = array[high];

            while(low < high && array[low] <= array[high]) {
                ++low;
            }
             array[high] = array[low];
        }

实例:

这里写图片描述

因为进不去第一个while循环语句,所以直接把array[high]的值给array[low].

while(low < high && array[high] >= tmp) {
                --high;
            }
             array[low] = array[high];

这里写图片描述

然后进入第二个while循环:

while(low < high && array[low] <= array[high]) {
                ++low;
            }
             array[high] = array[low];

这里写图片描述

这里写图片描述

这里写图片描述

不满足第二个while循环,跳出,把array[low]的值给array[high]:

这里写图片描述

又开始外面的大while循环,这次条件满足,可以进入第一个while循环:

这里写图片描述

这里写图片描述

现在不满足第一个while循环的条件,跳出,把array[high]的值给array[low]:

这里写图片描述

再次进入第二个while循环:

这里写图片描述

条件不满足,跳出,把array[low]的值给array[high]:

这里写图片描述

再一次开始外面的大while循环 :

进入第一个while循环:

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

因为low=high,跳出外面的大while循环:

这里写图片描述

外面的大while循环完成,跳出,比较完一趟,确定了选的基准的有序位置,然后在再这个有序元素进行两边同样的比较,直至所有的元素位置都确定了就排序完了。

递归法

package javapaixu;

import java.util.Arrays;

/**
 * 快速排序,递归实现
 * 时间复杂度:好:O(无序)(nlog2n),坏(有序):O(n^2)
 * 空间复杂度:
 * 稳定性:不稳定
 * @author 李正全
 */
public class Kuaisu {
    public static int partion(int[] array,int low,int high) {//一趟快排
        int tmp = array[low];
        while(low < high) {
            while(low < high && array[high] >= tmp) {
                --high;
            }
             array[low] = array[high];

            while(low < high && array[low] <= array[high]) {
                ++low;
            }
             array[high] = array[low];

        }
        array[low] = tmp;
        return low;
    }   

    public static void Quick(int[] array,int start,int end) {
        int par = partion(array,start,end);
        if(par > start+1) {//左边
            Quick(array,start,par-1);
        }
        if(par < end-1) {//右边
            Quick(array,par+1,end);
        }
    }

    public static void QuickSort(int[] array) {
         Quick(array,0,array.length-1);
     }


    public static void main(String[] args) {
        int[] array = {20,1,9,56,25,32,87,45,12,69,54,19};
        QuickSort(array);
        System.out.println(Arrays.toString(array));
    }

}

运行结果:

[1, 9, 12, 19, 20, 25, 32, 45, 54, 56, 69, 87]

非递归法

就是用队列的方式去实现:

package javapaixu;

import java.util.Arrays;

/**
 * 快速排序,非递归实现
 * 时间复杂度:好:O(无序)(nlog2n),坏(有序):O(n^2)
 * 空间复杂度:
 * 稳定性:不稳定
 * @author 李正全
 */
public class Kuaisu1 {
    public static int partion(int[] array,int low,int high) {//一趟快排
        int tmp = array[low];
        while(low < high) {
            while(low < high && array[high] >= tmp) {
                --high;
            }
            if(low >= high) {
                break;
            }else {
                array[low] = array[high];
            }
            while(low < high && array[low] <= array[high]) {
                ++low;
            }
            if(low >= high) {
                break;
            }else {
                array[high] = array[low];
            }
        }
        array[low] = tmp;
        return low;
    }   
    public static void QuickSort(int[] array) {
        int[] stack = new int[array.length];
        int top = 0;
        int low = 0;
        int high = array.length-1; 
        int par = partion(array,low,high);
         //入栈
            if(par > low+1) {
                stack[top++] = low;
                stack[top++] = par-1;
            }

            if(par < high-1) {
                stack[top++] = par+1;
                stack[top++] = high;
            }

            //出栈
            while(top > 0) {
                high = stack[--top];
                low = stack[--top];
                par = partion(array,low,high);

                if(par > low+1) {
                    stack[top++] = low;
                    stack[top++] = par-1;
                }

                if(par < high-1) {
                    stack[top++] = par+1;     
                    stack[top++] = high;
                }
            }
        }


    public static void main(String[] args) {
        int[] array = {1,9,56,25,32,7,87,45,12,20,69,3,54,19};
        QuickSort(array);
        System.out.println(Arrays.toString(array));

    }

}

运行结果:

[1, 3, 7, 9, 12, 19, 20, 25, 32, 45, 54, 56, 69, 87]

猜你喜欢

转载自blog.csdn.net/qq2899349953/article/details/80326030