算法练习(十四)常用的排序算法实现

1、冒泡算法

public void bubbleSortOpt(int[] arr) {
    int temp = 0;
    for(int i = 0; i < arr.length - 1; i++) {
        for(int j = 0; j < arr.length - i - 1; j++) {	//arr.length-i-1后面的是已排序空间
            if(arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

2、快速排序

public void quicksort(int[] arr, int start, int end) {
	if(start < end) {
        // 把数组中的首位数字作为基准数
        int stard = arr[start];
        // 记录需要排序的下标
        int low = start;
        int high = end;
        // 循环找到比基准数大的数和比基准数小的数
        while(low < high) {
            // 右边的数字比基准数大
            while(low < high && arr[high] >= stard) {
                high--;
            }
            // 使用右边的数替换左边的数
            arr[low] = arr[high];
            // 左边的数字比基准数小
            while(low < high && arr[low] <= stard) {
                low++;
            }
            // 使用左边的数替换右边的数
            arr[high] = arr[low];
        }
        // 把标准值赋给下标重合的位置
        arr[low] = stard;
        // 处理所有小的数字
        quickSort(arr, start, low);
        // 处理所有大的数字
        quickSort(arr, low + 1, end);
    }
}

3、直接插入排序

public void insertSort(int[] arr) {
	for(int i = 1; i < arr.length - 1; i++) {
        // 当前数字比前一个数字小
        if(arr[i] < arr[i - 1]) {
            int j;
            // 把当前遍历的数字保存起来
            int temp = arr[i];
            for(j = i - 1; j >= 0 && arr[j] > temp; j--) {
                // 前一个数字赋给后一个数字
                arr[j + 1] = arr[j];
            }
            // 把临时变量赋给不满足条件的后一个元素
            arr[j + 1] = temp;
        }
    }
}

4、希尔排序

public void shellSort(int[] arr) {
    // gap 为步长,每次减为原来的一半。
    for (int gap = arr.length / 2; gap > 0; gap /= 2) {
        // 对每一组都执行直接插入排序
        for (int i = 0 ;i < gap; i++) {
            // 对本组数据执行直接插入排序
            for (int j = i + gap; j < arr.length; j += gap) {
                // 如果 a[j] < a[j-gap],则寻找 a[j] 位置,并将后面数据的位置都后移
                if (arr[j] < arr[j - gap]) {
                    int k;
                    int temp = arr[j];
                    for (k = j - gap; k >= 0 && arr[k] > temp; k -= gap) {
                        arr[k + gap] = arr[k];
                    }
                    arr[k + gap] = temp;
                }
            }
        }
    }
}

5、选择排序

public static void selectSort(int[] array){
    for (int bound = 0; bound < array.length-1 ; bound++) {
        //[0,bound)为已排序区间bound位置元素为擂主,循环取出待排序区间元素与擂主比较
        //如果小就交换(即打擂成功)
        for(int cur = bound+1;cur < array.length;cur++){
            if(array[bound] > array[cur]){  //打擂成功
                int temp = array[bound];
                array[bound] = array[cur];
                array[cur] = temp;
            }
        }
    }
}

6、堆排序

public static void heapSort(int[] array){
    //先建大堆
    CreatHeap(array);
    //循环把堆顶元素交换到最后,并调整堆
    for (int i = 0; i < array.length-1; i++) {
        //当堆中只剩一个元素,也不需要进行调整,本来就是有序的
        swap(array,0,array.length-1-i); //堆中元素个数为length-i,所以最后一个元素下标为length-i-1
        //交换完之后把最后一个元素删掉
        //堆的长度又进一步缩水了
        //数组中
        //[0,array.length-i-1)为待排序区间
        //[array.length-i-1,array.length)为已排序区间
        shiftDown(array,array.length-i-1,0);
    }
}

    public static void CreatHeap(int[] array) {
        //从最后一个非叶子节点出发向前循环,依次进行向下调整
        for(int i = (array.length-1-1)/2;i >=0;i--){
            shiftDown(array,array.length,i);
        }
    }

    public static void shiftDown(int[] array, int heapLength, int index) {
        int parent = index;
        int child = index*2 +1;
        while(child <heapLength){
            if(child+1 < heapLength && array[child+1] > array[child]){
                child = child +1;
            }
            //条件结束,child已经指向左右子树中较大的数
            if(array[child] > array[parent]){
                swap(array,child,parent);
            }
            parent = child;
            child = parent*2+1;
        }

    }

    public static void swap(int[] array,int i, int j){
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
}

7、归并排序

/**
 * 合并数组
 */
public static void merge(int[] arr, int low, int middle, int high) {
    // 用于存储归并后的临时数组
    int[] temp = new int[high - low + 1];
    // 记录第一个数组中需要遍历的下标
    int i = low;
    // 记录第二个数组中需要遍历的下标
    int j = middle + 1;
    // 记录在临时数组中存放的下标
    int index = 0;
    // 遍历两个数组,取出小的数字,放入临时数组中
    while (i <= middle && j <= high) {
        // 第一个数组的数据更小
        if (arr[i] <= arr[j]) {
            // 把更小的数据放入临时数组中
            temp[index] = arr[i];
            // 下标向后移动一位
            i++;
        } else {
            temp[index] = arr[j];
            j++;
        }
        index++;
    }
    // 处理剩余未比较的数据
    while (i <= middle) {
        temp[index] = arr[i];
        i++;
        index++;
    }
    while (j <= high) {
        temp[index] = arr[j];
        j++;
        index++;
    }
    // 把临时数组中的数据重新放入原数组
    for (int k = 0; k < temp.length; k++) {
        arr[k + low] = temp[k];
    }
}

/**
 * 归并排序
 */
public static void mergeSort(int[] arr, int low, int high) {
    int middle = (high + low) / 2;
    if (low < high) {
        // 处理左边数组
        mergeSort(arr, low, middle);
        // 处理右边数组
        mergeSort(arr, middle + 1, high);
        // 归并
        merge(arr, low, middle, high);
    }
}

8、基数排序

/**
 * 基数排序
 */
public static void radixSort(int[] arr) {
    // 存放数组中的最大数字
    int max = Integer.MIN_VALUE;
    for (int value : arr) {
        if (value > max) {
            max = value;
        }
    }
    // 计算最大数字是几位数
    int maxLength = (max + "").length();
    // 用于临时存储数据
    int[][] temp = new int[10][arr.length];
    // 用于记录在 temp 中相应的下标存放数字的数量
    int[] counts = new int[10];
    // 根据最大长度的数决定比较次数
    for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
        // 每一个数字分别计算余数
        for (int j = 0; j < arr.length; j++) {
            // 计算余数
            int remainder = arr[j] / n % 10;
            // 把当前遍历的数据放到指定的数组中
            temp[remainder][counts[remainder]] = arr[j];
            // 记录数量
            counts[remainder]++;
        }
        // 记录取的元素需要放的位置
        int index = 0;
        // 把数字取出来
        for (int k = 0; k < counts.length; k++) {
            // 记录数量的数组中当前余数记录的数量不为 0
            if (counts[k] != 0) {
                // 循环取出元素
                for (int l = 0; l < counts[k]; l++) {
                    arr[index] = temp[k][l];
                    // 记录下一个位置
                    index++;
                }
                // 把数量置空
                counts[k] = 0;
            }
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值