首页 > 编程语言 > 详细

排序算法总结

时间:2020-06-20 22:24:58      阅读:99      评论:0      收藏:0      [点我收藏+]

插入排序

从未排序序列的最左端开始拿取一个数据,与已排序序列从右向左进行比较,如果未排序数据大于已排序序列则插入在这个已排序的数据的后面。

    public static int[] insertionSort(int[] array) {
        if (array.length == 0)
            return array;
        int current;
        for (int i = 0; i < array.length - 1; i++) {
            current = array[i + 1];
            int preIndex = i;
            while (preIndex >= 0 && current < array[preIndex]) {
                array[preIndex + 1] = array[preIndex];
                preIndex--;
            }
            array[preIndex + 1] = current;
        }
        return array;
    }

 

 

希尔排序

插入排序的升级版,就是按照增量gap来分组,每间隔gap的数据为一组,每组分别进行简单插入排序,gap从length/2开始,每次gap=gap/2,直到gap=1,就相当于简单插入排序了。

实质就是通过按照增量gap,分成不同的组,每组提前进行简单插入排序,可以提前缩小数据之间的波动幅度,所以当gap=1的时候,整个序列的差异已经小了很多,这就是希尔排序在简单插入排序的基础之上进行的优化,以至于时间复杂度进入O(n2)以内。

代码

    public static int[] ShellSort(int[] array) {
        int len = array.length;
        int temp, gap = len / 2;
        while (gap > 0) {
            for (int i = gap; i < len; i++) {
                temp = array[i];
                int preIndex = i - gap;
                while (preIndex >= 0 && array[preIndex] > temp) {
                    array[preIndex + gap] = array[preIndex];
                    preIndex -= gap;
                }
                array[preIndex + gap] = temp;
            }
            gap /= 2;
        }
        return array;
    }

 

 

选择排序

在未排序序列中选出最小值,放在已排序序列的最后边

代码

    public static int[] selectionSort(int[] array) {
        if (array.length == 0)
            return array;
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i; j < array.length; j++) {
                if (array[j] < array[minIndex]) //找到最小的数
                    minIndex = j; //将最小数的索引保存
            }
            int temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        }
        return array;
    }

 

 

冒泡排序

未排序序列中相邻两两数据相比较,如果前边的大于后边的,则交换,一直移动到未排序序列结束

    public static int[] bubbleSort(int[] array) {
        if (array.length == 0)
            return array;
        for (int i = 0; i < array.length; i++)
            for (int j = 0; j < array.length - 1 - i; j++)
                if (array[j + 1] < array[j]) {
                    int temp = array[j + 1];
                    array[j + 1] = array[j];
                    array[j] = temp;
                }
        return array;
    }

 

 

归并排序

归并排序利用了分治法的思想,通过递归将整个序列分为划分为越来越小的子序列,直到每个子序列都不可再分,则对子序列进行排序,然后合并已排序的子序列。

特点:稳定,但是需要额外的空间

代码

public class MergeSort {

    public static void merSort(int[] arr,int left,int right){

        if(left<right){
            int mid = (left+right)/2;
            merSort(arr,left,mid);//左边归并排序,使得左子序列有序
            merSort(arr,mid+1,right);//右边归并排序,使得右子序列有序
            merge(arr,left,mid,right);//合并两个子序列
        }
    }
    private static void merge(int[] arr, int left, int mid, int right) {
        int[] temp = new int[right - left + 1];//ps:也可以从开始就申请一个与原数组大小相同的数组,因为重复new数组会频繁申请内存
        int i = left;
        int j = mid+1;
        int k = 0;
        while(i<=mid&&j<=right){
            if (arr[i] < arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[k++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[k++] = arr[j++];
        }
        //将temp中的元素全部拷贝到原数组中
        for (int k2 = 0; k2 < temp.length; k2++) {
            arr[k2 + left] = temp[k2];
        }
    }
    public static void main(String args[]){
        int[] test = {9,2,6,3,5,7,10,11,12};
        merSort(test,0,test.length-1);
        for(int i=0; i<test.length;i++){
            System.out.print(test[i] + " ");
        }
    }


}

 

快速排序

快速排序也是利用了分治法的思想,

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

代码

public class TestQuickSort {
       private static int partition(int[] arr, int low, int high) {
               //指定左指针i和右指针j
               int i = low;
               int j= high;
               
               //将第一个数作为基准值。挖坑
               int x = arr[low];
               
               //使用循环实现分区操作
               while(i<j){//5  8
                       //1.从右向左移动j,找到第一个小于基准值的值 arr[j]
                       while(arr[j]>=x && i<j){
                               j--;
                       }
                       //2.将右侧找到小于基准数的值加入到左边的(坑)位置, 左指针想中间移动一个位置i++
                       if(i<j){
                               arr[i] = arr[j];
                               i++;
                       }
                       //3.从左向右移动i,找到第一个大于等于基准值的值 arr[i]
                       while(arr[i]<x && i<j){
                               i++;
                       }
                       //4.将左侧找到的打印等于基准值的值加入到右边的坑中,右指针向中间移动一个位置 j--
                       if(i<j){
                               arr[j] = arr[i];
                               j--;
                       }
               }
               
               //使用基准值填坑,这就是基准值的最终位置
               arr[i] = x;//arr[j] = x;
               //返回基准值的位置索引
               return i; //return j;
       }
       private static void quickSort(int[] arr, int low, int high) {//???递归何时结束
               if(low < high){
                       //分区操作,将一个数组分成两个分区,返回分区界限索引
                       int index = partition(arr,low,high);
                       //对左分区进行快排
                       quickSort(arr,low,index-1);
                       //对右分区进行快排
                       quickSort(arr,index+1,high);
               }
       
       }
       public static void quickSort(int[] arr) {
               int low = 0;
               int high = arr.length-1;
               quickSort(arr,low,high);
       }
       
       public static void main(String[] args) {
               //给出无序数组
               int arr[] = {72,6,57,88,60,42,83,73,48,85};
       //输出无序数组
       System.out.println(Arrays.toString(arr));
       //快速排序
       quickSort(arr);
       //partition(arr,0,arr.length-1);
       //输出有序数组
       System.out.println(Arrays.toString(arr));
       }
       
}

 

堆排序

通过构造最大堆或者最小堆,交换顶堆元素与未排序序列元素,然后重新构造最大堆或者最小堆,直到已排序序列为n-1

步骤

  • 构造最大堆
  • 交换最大堆元素与未排序序列最后的元素
  • 重新构造最大堆
  • 直到已排序序列为n-1

代码

//声明全局变量,用于记录数组array的长度;
static int len;
    /**
     * 堆排序算法
     *
     * @param array
     * @return
     */
    public static int[] HeapSort(int[] array) {
        len = array.length;
        if (len < 1) return array;
        //1.构建一个最大堆
        buildMaxHeap(array);
        //2.循环将堆首位(最大值)与末位交换,然后在重新调整最大堆
        while (len > 0) {
            swap(array, 0, len - 1);
            len--;
            adjustHeap(array, 0);
        }
        return array;
    }
    /**
     * 建立最大堆
     *
     * @param array
     */
    public static void buildMaxHeap(int[] array) {
        //从最后一个非叶子节点开始向上构造最大堆
        for (int i = (len/2 - 1); i >= 0; i--) { //感谢 @让我发会呆 网友的提醒,此处应该为 i = (len/2 - 1) 
            adjustHeap(array, i);
        }
    }
    /**
     * 调整使之成为最大堆
     *
     * @param array
     * @param i
     */
    public static void adjustHeap(int[] array, int i) {
        int maxIndex = i;
        //如果有左子树,且左子树大于父节点,则将最大指针指向左子树
        if (i * 2 < len && array[i * 2] > array[maxIndex])
            maxIndex = i * 2;
        //如果有右子树,且右子树大于父节点,则将最大指针指向右子树
        if (i * 2 + 1 < len && array[i * 2 + 1] > array[maxIndex])
            maxIndex = i * 2 + 1;
        //如果父节点不是最大值,则将父节点与最大值交换,并且递归调整与父节点交换的位置。
        if (maxIndex != i) {
            swap(array, maxIndex, i);
            adjustHeap(array, maxIndex);
        }
    }

 

排序算法总结

原文:https://www.cnblogs.com/flyandling/p/13170575.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!