常见排序算法

来源:互联网 发布:$sql 编辑:程序博客网 时间:2024/06/11 07:21
/* * 排序算法: *      交换排序:快速排序(O(NlogN),不稳定)、冒泡排序(O(N^2),稳定) *      插入排序:直接插入排序(O(N^2),稳定)、希尔排序(O(N^1.3)不稳定) *      选择排序:直接选择排序(O(N^2),不稳定),堆排序(O(NlogN),不稳定) *      归并排序(O(NlogN),稳定) */public class Sort {    /*     * 1.快速排序,该方法有三个参数,数组arr,需要进行排序的部分数组(由low和high截取),然后找     * 一个基准值(一般为需要排序的数组的第一个元素),确定基准值所在的位置(start=end时),再使用     * 递归对基准值两边的元素继续进行快排。     *      * 简言之,快排第一步就是确定基准值的位置,然后再进行递归求解。     */    public static void quicklySort(int arr[], int low, int high) {        int key = arr[low];        int start = low;        int end = high;        while (start < end){            while (arr[end] >= key && start < end){                end--;            }            arr[start] = arr[end];            while (arr[start] <= key && start < end){                start++;            }            arr[end] = arr[start];        }        arr[start] = key; // 将基准值填到相应位置        if (start > low)            quicklySort(arr, low, start - 1);        if (end < high)            quicklySort(arr, end + 1, high);    }    /*     * 2.冒泡排序,遇见比当前数小的就交换顺序     */    public static void bubbleSort(int arr[]) {        int temp;        for (int i = 0; i < arr.length; i++){            for (int j = arr.length - 1; j > i; j--){ //从后往前冒,当然也可以从前往后沉                if (arr[j] < arr[j - 1]){                    temp = arr[j];                    arr[j] = arr[j - 1];                    arr[j - 1] = temp;                }            }        }    }    /*     * 3.直接插入排序,假设数组第一个元素自成一个有序序列,从第二个元素起,依次与前面的元素进行     * 比较,插入到正确的位置以构成有序序列,直到最后一个元素插入到正确位置从而使得整个数组有序。     */    public static void insertionSort(int arr[]) {        int temp;        for (int i = 1; i < arr.length; i++){ //i表示从哪个位置的元素开始与它之前的元素进行比较            int j = i;            while (j > 0 && arr[j] < arr[j - 1] ){//这里不用for循环是因为使用for循环则无论arr[j]是否小于arr[j-1],都要进行j--的操作                temp = arr[j];                arr[j] = arr[j - 1];                arr[j - 1] = temp;                j--;            }        }    }    /*     * 4.希尔排序,改进的直接插入排序,先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行     * 直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入     * 排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有     * 较大提高。步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作。     */    public static void shellSort(int arr[]) {        int increment;        for (increment = arr.length / 2; increment > 0; increment /= 2){            //增量之后进行直接插入排序            for (int j = increment; j < arr.length; j++){                if (arr[j] < arr[j - increment]){                    int temp = arr[j];                    int k = j - increment;                    while (k >= 0 && arr[k] > temp){                        arr[k + increment] = arr[k];                        k -= increment;                    }                    arr[k + increment] = temp;                }            }        }    }    /*     * 5.直接选择排序,思想就是从第一个元素开始遍历数组,找到数组中的最小元素跟第一个元素交换     * 位置,然后接着从第二个元素开始重复刚才的过程,直到最后一个元素,跟冒泡不同,直接选择排序     * 是每一次遍历只交换一次元素,而冒泡则是只要发现当前元素比前面的元素小就要交换位置。     */    public static void selectionSort(int arr[]) {        int min;//记录最小元素的索引位置        int temp;        for (int i = 0; i < arr.length - 1; i++){            min = i;            for (int j = i + 1; j < arr.length; j++){                if (arr[j] < arr[min]){                    min = j;                }            }            temp = arr[i];            arr[i] = arr[min];            arr[min] = temp;        }    }    /*     * 6.堆排序,升序构建最大堆(父大于子),     * 首先,构建最大堆buildMaxHeap();需要借助筛选函数heapScreen();     * 其次,将堆顶元素跟堆得最后一个元素交换位置(最大值放后边)     *      */    //n为构建堆的节点总数    public static void buildMaxHeap(int arr[], int n) {        //1.构建最大堆        for (int i = (n - 1) / 2; i >= 0; i--){//从最后一个非叶子结点开始筛选 i = (n - 1) / 2            heapScreen(arr, i, n);        }    }    //筛选,即调整元素位置,使之满足最大堆的性质,i为开始节点,n为节点总数     public static void heapScreen(int arr[], int i, int n) {        int temp = arr[i];        int j = 2 * i + 1;//左孩子        while (j < n){            if (j + 1 < n && arr[j] < arr[j + 1])                j++;            if (arr[j] <= temp)                break;            arr[i] = arr[j];            i = j;            j = 2 * i + 1;        }        arr[i] = temp;    }    public static void heapSort(int arr[]) {        for (int i = arr.length; i > 0; i-- ){            buildMaxHeap(arr,i);            System.out.println(arr[0]);            //注意:这里交换元素不能用swap函数,这涉及到引用传递的问题。详情见博客            int temp = arr[0];            arr[0] = arr[i - 1];            arr[i - 1] = temp;        }    }    /*7、归并排序     * 步骤:先递归拆分(sort),然后合并(merge),排序在合并中实现     */    public static void mergeSort(int arr[]){        sort(arr, 0, arr.length - 1);    }    public static void sort(int arr[], int low, int high) {        if (low < high){            int mid = (low + high) / 2;            sort(arr, 0, mid);            sort(arr, mid + 1, high);            merge(arr, low, mid, high);        }    }    public static void merge(int arr[], int low, int mid, int high) {        int i = low;        int j = mid + 1;        int temp[] = new int[arr.length];//定义长度为arr.length的数组是为了下标能跟arr对上        int k = low;//临时数组temp的下标        while (i <= mid && j <= high){            if (arr[i] <= arr[j])                temp[k++] = arr[i++];            else                temp[k++] = arr[j++];        }        while (i <= mid)            temp[k++] = arr[i++];        while (j <= high)            temp[k++] = arr[j++];        for (int n = low; n <= high; n++)            arr[n] = temp[n];    }}
0 0
原创粉丝点击