首页 > 编程语言 >Java实现排序算法(1)

Java实现排序算法(1)

时间:2024-04-05 21:31:36浏览次数:18  
标签:minIndex Java temp int 元素 算法 下标 array 排序

七大常见排序算法

  1. 直接插入排序
  2. 希尔排序
  3. 选择排序
  4. 堆排序
  5. 冒泡排序
  6. 快速排序
  7. 归并排序

下文后三种排序算法(后三种排序算法详解)

直接插入排序

算法描述:

  • 定义两个下标(i 和 j).i 从第二个元素开始,j 从 i 前面开始,进行循环,
  • 途中定义一个 temp ,每次循环将 i 下标的元素放到 temp 中,与 j 进行比较转换(当 j 下标的元素大于 temp 中的元素,就将 j 位置的元素赋值给后一个元素,即i下标元素,j-- 继续与 temp 比较)
  • 当 j-- 到小于 temp 中的元素时,一次循环就完成了,此后 i++ 继续重复如上循环.
    描述虽复杂,烦请与算法实现步骤图结合思考.
    直接插入排序
    代码实现:
public class InsertSort {
    public void iSort(int[] array) {
        for (int i = 1; i < array.length; i++) {  // 从第二个元素开始(因为当数组只有一个元素时是有序的)
            int temp = array[i];                // 设置一个 temp(为 i 下标的值) ,方便后续交换
            int j = i-1;                        // 设置一个 j,让 j 为 i 的前一个,在循环的过程中与 temp 中的元素进行交换
            for (; j >= 0; j--) {               // j 与 temp 每次比较完向前移动,继续和前一个元素进行对比
                if (array[j] > temp){            // 即前一个元素(j)大于后一个元素(j+1/temp),进行交换,j --
                    array[j+1] = array[j];       // 将前一个元素(j)赋值给后一个元素(j+1/temp)
                }else {                         // 后前一个元素小于后一个元素
                    break;                     // 当前面一个元素比后面小的时候,就证明前面已经是有序的了,就不需要排序了,直接退出循环
                }
            }             // 出循环,j--
            array[j+1] = temp;  // 用 temp 覆盖 j 的前一个元素
        }  // 出循环,i++
    }

    public static void main(String[] args) {
        InsertSort sort = new InsertSort();
        int[] array = {12,45,32,56,8};
        sort.iSort(array);
        System.out.println(Arrays.toString(array));
    }
}

输出结果:
在这里插入图片描述

稳定性:稳定
时间复杂度:O(n^2)

希尔排序

插入排序的一种优化. 每次排序前进行分组,每组采用插入排序. 每次分组会越来越少.直到分为一组
在这里插入图片描述

代码实现:

public class SellSort {
    public void sellSort(int[] array){
        int grp = array.length;   // grp 为分多少组,先分 array.length 组
        while (grp > 1){          // 缩小增量
            sell(array,grp);
            grp /= 2;  // 每次排序完对数组再分半
        }
        // 整体进行插入排序
        sell(array,1);  // 最终会将 grp 分为一组
    }

    private void sell(int[] array,int grp) {   // 希尔排序,进行分组排序. 每组采用插入排序
        for (int i = grp; i < array.length; i++) {
            int temp = array[i];
            int j = i-grp;
            for (; j >= 0; j -= grp) {
                if (array[j] > temp){
                    array[j+grp] = array[j];
                }else {
                    break;
                }
            }
            array[j+grp] = temp;
        }
    }

    public static void main(String[] args) {
        SellSort sort = new SellSort();
        int[] array = {12,45,32,56,8,22};
        sort.sellSort(array);
        System.out.println(Arrays.toString(array));
    }
}

输出结果:
在这里插入图片描述

稳定性:不稳定
时间复杂度: O(n^1.3) - O(n^1.5)

选择排序

第一种:
算法描述:

  • 定义两个下标(i,j),i 为第一个元素下标,j 为后一个元素下标.
  • 循环开始时将 i 下标存到 minIndex 中, j 往后循环,过程中找到比 i 下标元素小的下标放到 minIndex 中
  • 当 j 循环完,将 i 位置的元素与 minIndex 位置的元素进行交换.
  • i++ ,重复如上循环.
    在这里插入图片描述
    代码实现:
/*
    * 选择排序第一种方法
    * */
    public void  selectSort(int[] array){
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            int j = i+1;     // j 为 i 的前一个
            for (; j <array.length ; j++) {
                if (array[j] < array[minIndex]) {  // 如果当前 j 位置的元素小于 minIndex 下标的元素,就将 j 赋值给 minIndex
                    minIndex = j;
                }
            }
            swap(array,i,minIndex);
        }
    }

    private void swap(int[] array,int i,int minIndex){
        int temp = array[i];
        array[i] = array[minIndex];
        array[minIndex] = temp;
    }
    
	public static void main(String[] args) {
        SelectSort sort = new SelectSort();
        int[] array = {12,45,32,56,8};
        sort.selectSort(array);
        System.out.println("第一种方法排序:" + Arrays.toString(array));

        int[] array2 = {77,21,45,6,41};
        sort.selectSort2(array2);
        System.out.println("第二种方法排序:" + Arrays.toString(array2));
    }

输出结果:在这里插入图片描述

第二种:
算法描述:直接看代码注释更加明了.
请添加图片描述
代码实现:

/*
    * 选择排序第二种方法
    * */
    public void  selectSort2(int[] array){
        int left = 0;   // 定义一个 left 下标(数组第一个元素)
        int right = array.length-1; // 定义一个 right下标(数组最后一个元素)
        while (left < right){
            int minIndex = left;  // 假设最小元素的下标为 left
            int maxIndex = left; // 假设最大元素的下标为 left
            for (int i = left+1; i <= right; i++) {
                if (array[i] < array[minIndex]){  // i 下标元素小于 minIndex 下标元素
                    minIndex = i;
                }
                if (array[i] > array[maxIndex]) {  // i 下标元素大于 maxIndex 下标元素
                    maxIndex = i;
                }
            }
            // i 循环结束. 进行交换,元素值小放左边,元素值大放右边
            swap(array,minIndex,left);
            if (maxIndex == left){   // 特殊情况. 当最大元素为数组第一个元素时(left),此时 minIndex 与 left 进行交互时会将 maxIndex 记录的最大值下标替换掉,改为记录 minIndex.
                maxIndex = minIndex;
            }
            swap(array,maxIndex,right);
            left++;
            right--;
        }
    }

输出结果:
在这里插入图片描述

稳定性:不稳定
时间复杂度:O(n^2)

堆排序

先将数组转换成一个大根堆,再由大根堆进行排序.

创建大根堆

算法描述:

  • 定义一个循环,循环初始值为 parent(父亲结点)= (useSize-1-1)/2.(其中 useSize 为待排序数组的大小)
  • 定义一个 child(孩子结点).其中 child 结点一定是左右孩子中最大的结点.将这两个结点进行比较,大的结点就会被放到 parent 结点的位置.
  • 将 parent 移向 child 的位置,child 移向 (parent*2+1) 的位置,继续判断以 child 为根结点下面的树是否为大根堆.
  • 上述 parent 一直减减,直到 parent 为 0,大根堆就创建好了
    在这里插入图片描述
    代码实现:
public class HeapSort {
    public int[] elem;  // 被创建堆的数组(堆底层就是一个数组)
    public int useSize;   // 记录数组中元素个数

    public HeapSort(){
        this.elem = new int[10];   // 设定数组大小为10
    }
    
    public void initElem(int[] array){  // 初始化 数组
        for (int i = 0; i < array.length; i++) {
            elem[i] = array[i];
            useSize++;  // 记录 elem 中有多少个元素,即为 elem 数组大小
        }
    }

    public void createHeap(){   // 创建大根堆
        for (int parent = (useSize-1-1)/2; parent >= 0; parent--) {     // useSize-1 是数组最后一个元素下标. 再 (-1) / 2 是其根节点的下标
            shiftDown(parent,useSize);
        }
    }

    private void shiftDown(int parent, int len) { // 创建大根堆的具体方法
        int child = parent*2+1;  // 二叉树中左孩子下标
        while (child < len){   // 即保证这个二叉树有左孩子
            if (child+1 < len && elem[child] < elem[child+1]){  // 在有右孩子的情况下,判断右孩子是否比左孩子大. 其中 child 永远是左右孩子最大值的下标
                child++; // 将 child 移向右孩子
            }
            if(elem[child] > elem[parent]){   // 孩子结点比父亲结点大
                // 进行交换
                int temp = elem[child];
                elem[child] = elem[parent];
                elem[parent]= temp;
                // 将 parent 移到 child 这里,继续判断以 child 为根结点下面的树是否为大根堆
                parent = child;
                child = parent*2+1;
            }else {  // 孩子结点没父亲结点大
                break;       // 下面的树已经是大根堆了,无需操作
            }
        }
    }
    public static void main(String[] args) {
        /*
        *  测试创建大根堆
        * */
      HeapSort elem = new HeapSort();
      int[] array = {27,15,19,18,28,33,66,50,25,38};
      elem.initElem(array);  // 初始化数组
      elem.createHeap(); // 根据初始数组创建大根堆
      System.out.println("dd");  // 调试查看结果

        /*
        *  测试堆排序
        * */
      elem.heapSort();
      System.out.println("cc");
    }
 }

输出结果:展开为大根堆
在这里插入图片描述

进行堆排序

算法描述:看图和代码注释更加明了.
在这里插入图片描述
代码实现:

/*
    * 进行堆排序
    * 使用大根堆进行排序
    * */
    public void heapSort(){
        int end = useSize - 1;
        while (end > 0){    // 当 end 等于0的时候,此时已经有序了,没必要再进行比较了
            swap(elem,0,end);   // 将最后一个位置的元素与堆顶元素交换
            shiftDown(0,end); // 交换后,以第一个元素为 parent ,调整大根堆
            end--; //
        }
    }
    private void swap(int[] arr,int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

输出结果:
在这里插入图片描述

稳定性:不稳定
时间复制度:O(n* )

标签:minIndex,Java,temp,int,元素,算法,下标,array,排序
From: https://blog.csdn.net/m0_64304792/article/details/137022602

相关文章