8种常见排序算法的java实现

关于常见的排序算法,常用排序算法总结(一)这篇文章写的很详细了,本文主要是把其中的算法用java语言实现一遍

1.冒泡排序

    public static void swap(int[] arr, int i, int j) {
        arr[i] = arr[i] + arr[j];
        arr[j] = arr[i] - arr[j];
        arr[i] = arr[i] - arr[j];
    }

    public static void bubbleSort(int[] arr) {
        boolean didSwap;
        for (int i = 0, len = arr.length; i < len - 1; i++) {
            didSwap = false;
            for (int j = 0; j < len - i - 1; j++) {
                if (arr[j + 1] < arr[j]) {
                    swap(arr, j, j + 1);
                    didSwap = true;
                }
            }
            //添加这一步,才能使排序最好O(n)
            if (didSwap == false) {
                return;
            }
        }
    }

    /**
     * 鸡尾酒排序
     * @param a
     * @param n
     */
    public static void cocktailSort(int[] a, int n) {
        int left = 0;                            // 初始化边界
        int right = n - 1;
        while (left < right) {
            for (int i = left; i < right; i++)   // 前半轮,将最大元素放到后面
            {
                if (a[i] > a[i + 1]) {
                    swap(a, i, i + 1);
                }
            }
            right--;
            for (int i = right; i > left; i--)   // 后半轮,将最小元素放到前面
            {
                if (a[i - 1] > a[i]) {
                    swap(a, i - 1, i);
                }
            }
            left++;
        }
    }

2.选择排序

    public static void selectSort(int[] a){
        if(a == null || a.length < 2){
            return;
        }

        for(int i = 0; i < a.length - 1; i++){
            int min = i;
            int minVal = a[i];
            for (int j = i + 1; j < a.length ; j++) {
                if(a[j] < minVal){
                    min = j;
                    minVal = a[j];
                }
            }
            if(min != i){
                a[min] = a[i];
                a[i] = minVal;
            }
        }
    }

3.插入排序

public static void inserSort(int[] nums){
        if(nums == null || nums.length < 2){
            return;
        }

        for (int i = 1; i < nums.length; i++){
            int num  = nums[i];
            int j = i - 1;
            while (j >= 0 && num < nums[j]) {

                    nums[j+1] = nums[j];
                    j--;
            }
            nums[j + 1] = num;
        }
    }


    public static void main(String[] args) {
        int a[] = { 6, 5, 3, 1, 8, 7, 2, 4 }; 
        int n =a.length;
        inserSort(a);
        System.out.println("鸡尾酒排序结果:");
        for (int i = 0; i < n; i++)
        {
            System.out.println("i=" + a[i]);
        }
    }

4.希尔排序

 

/**
     * 全部元素分为几个区域来提升插入排序的性能。
     * 这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,
     * 算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)
     * 分类 -------------- 内部比较排序
     * 数据结构 ---------- 数组
     * 最差时间复杂度 ---- 根据步长序列的不同而不同。已知最好的为O(n(logn)^2)
     * 最优时间复杂度 ---- O(n)
     * 平均时间复杂度 ---- 根据步长序列的不同而不同。
     * 所需辅助空间 ------ O(1)
     * 稳定性 ------------ 不稳定
     *
     * @param a
     * @param n
     */
    static void shellSort(int a[], int n) {
        int h = 0;
        // 生成初始增量
        while (h <= n / 3)
        {
            h = 3 * h + 1;
        }
        while (h >= 1) {
            for (int i = h; i < n; i++) {
                int j = i - h;
                int get = a[i];
                while (j >= 0 && a[j] > get) {
                    a[j + h] = a[j];
                    j = j - h;
                }
                a[j + h] = get;
            }
            h = (h - 1) / 3;                    // 递减增量
        }
    }

5. 归并排序

/**
 * @description 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
 * 设定两个指针,最初位置分别为两个已经排序序列的起始位置
 * 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
 * 重复步骤3直到某一指针到达序列尾
 * 将另一序列剩下的所有元素直接复制到合并序列尾
 * @date 2018/7/12
 */
public class MergeSort {
    // 分类 -------------- 内部比较排序
    // 数据结构 ---------- 数组
    // 最差时间复杂度 ---- O(nlogn)
    // 最优时间复杂度 ---- O(nlogn)
    // 平均时间复杂度 ---- O(nlogn)
    // 所需辅助空间 ------ O(n)
    // 稳定性 ------------ 稳定
    // 合并两个已排好序的数组A[left...mid]和A[mid+1...right]
    public static void merge(int num[], int left, int mid, int right) {
        int len = right - left + 1;
        int[] tempArray = new int[len];       // 辅助空间O(n)
        int index = 0;
        int i = left;                   // 前一数组的起始元素
        int j = mid + 1;                // 后一数组的起始元素
        while (i <= mid && j <= right) {
            tempArray[index++] = num[i] <= num[j] ? num[i++] : num[j++];  // 带等号保证归并排序的稳定性
        }
        while (i <= mid) {
            tempArray[index++] = num[i++];
        }
        while (j <= right) {
            tempArray[index++] = num[j++];
        }
        for (int k = 0; k < len; k++) {
            num[left++] = tempArray[k];
        }
    }

    /**
     * 递归实现的归并排序(自顶向下)
     */
    public static void mergeSortRecursion(int num[], int left, int right) {
        // 当待排序的序列长度为1时,递归开始回溯,进行merge操作
        if (left == right) {
            return;
        }
        int mid = (left + right) / 2;
        mergeSortRecursion(num, left, mid);
        mergeSortRecursion(num, mid + 1, right);
        merge(num, left, mid, right);
    }

    /**
     * 非递归(迭代)实现的归并排序(自底向上)
     */
    public static void mergeSortIteration(int num[], int len) {
        // 子数组索引,前一个为num[left...mid],后一个子数组为num[mid+1...right]
        int left, mid, right;
        // 子数组的大小i初始为1,每轮翻倍
        for (int i = 1; i < len; i *= 2) {
            left = 0;
            // 后一个子数组存在(需要归并)
            while (left + i < len) {
                mid = left + i - 1;
                // 后一个子数组大小可能不够
                right = mid + i < len ? mid + i : len - 1;
                merge(num, left, mid, right);
                // 前一个子数组索引向后移动
                left = right + 1;
            }
        }
    }

    public static void main(String[] args) {

        int nums[] = {6, 5, 3, 1, 8, 7, 2, 4};      // 从小到大归并排序
        int nums2[] = {6, 5, 3, 1, 8, 7, 2, 4};
        int n1 = nums.length;
        int n2 = nums2.length;
        mergeSortRecursion(nums, 0, n1 - 1);          // 递归实现
        mergeSortIteration(nums2, n2);                 // 非递归实现
        System.out.println("递归实现的归并排序结果:");
        for (int i = 0; i < n1; i++) {
            System.out.println(nums[i]);
        }
        System.out.println();
        System.out.println("非递归实现的归并排序结果:");
        for (int i = 0; i < n2; i++) {
            System.out.println(nums2[i]);
        }
    }
}

6.堆排序

/**
 * @authore Xavier
 * @description 堆是一种近似完全二叉树的结构(通常堆是通过一维数组来实现的),
 * 并满足性质:以最大堆(也叫大根堆、大顶堆)为例,其中父结点的值总是大于它的孩子节点。
 * 由输入的无序数组构造一个最大堆,作为初始的无序区
 * 把堆顶元素(最大值)和堆尾元素互换
 * 把堆(无序区)的尺寸缩小1,并调用heapify(A, 0)从新的堆顶元素开始进行堆调整
 * 重复步骤2,直到堆的尺寸为1
 * @date 2018/6/3
 */
public class HeapSort {

    public static void sort(int[] a) {
        if (a == null || a.length < 2) {
            return;
        }

        System.out.println("开始排序");
        int arrayLength = a.length;
        //循环建堆
        for (int i = 0; i < arrayLength - 1; i++) {
            //建堆
            buildMaxHeap(a, arrayLength - 1 - i);
            //交换堆顶和最后一个元素
            swap(a, 0, arrayLength - 1 - i);
            System.out.println(Arrays.toString(a));
        }
    }

    private static void swap(int[] data, int i, int j) {
        int tmp = data[i];
        data[i] = data[j];
        data[j] = tmp;
    }

    //对data数组从0到lastIndex建大顶堆
    private static void buildMaxHeap(int[] data, int lastIndex) {
        //从lastIndex处节点(最后一个节点)的父节点开始
        for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
            //k保存正在判断的节点
            int k = i;
            //如果当前k节点的子节点存在
            while (k * 2 + 1 <= lastIndex) {
                //k节点的左子节点的索引
                int biggerIndex = 2 * k + 1;
                //如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在
                if (biggerIndex < lastIndex) {
                    //若果右子节点的值较大
                    if (data[biggerIndex] < data[biggerIndex + 1]) {
                        //biggerIndex总是记录较大子节点的索引
                        biggerIndex++;
                    }
                }
                //如果k节点的值小于其较大的子节点的值
                if (data[k] < data[biggerIndex]) {
                    //交换他们
                    swap(data, k, biggerIndex);
                    //将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
                    k = biggerIndex;
                } else {
                    break;
                }
            }
        }
    }

    public static void main(String[] args) {
        int a[] = {6, 5, 3, 1, 8, 7, 2, 4};   // 从小到大定向冒泡排序
        int n = a.length;
        sort(a);
        System.out.println("堆排序结果:");
        for (int i = 0; i < n; i++) {
            System.out.println("i=" + a[i]);
        }
    }

}

7.快速排序


    static void quick_sort(int s[]) {
        if (s == null || s.length < 2) {
            return;
        }

        int i = 0, j = s.length - 1, x = s[i];
        while (i < j) {
            // 从右向左找第一个小于x的数
            while (i < j && s[j] >= x) {
                j--;
            }
            if (i < j) {
                s[i++] = s[j];
            }
            // 从左向右找第一个大于等于x的数
            while (i < j && s[i] <= x) {
                i++;
            }
            if (i < j) {
                s[j--] = s[i];
            }
        }
        s[i] = x;

    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值