递进的方式 

  插入,希尔,归并

  冒泡,选择,快速

  堆排序(树里)

 

一:分析排序

1.哪几个方面

  时间效率

  空间效率

  交换次数

  稳定性

 

2.稳定性的意义

  

二:插入排序

1.理解

  可以理解成抓牌

 

2.代码

package com.jun.algorithm.foundation.thought;

import org.junit.Test;

import java.util.Arrays;

/**
 * 插入排序
 * 例如打牌场景就是如此
 * <p>
 * 具体的步骤:
 * 将数组分成已排序段和未排序段,初始化已排序段只有一个元素
 * 到未排序段取元素插入已排序段,保证有序
 * 重复上述操作
 * <p>
 * 稳定性:稳定
 *
 * @author caojun
 */
public class InsertSort {
    /**
     * 排序
     * 时间复杂度
     * n^2,最好的情况是n
     *
     * @param arr 要排序的数组
     * @return 排序后的数组
     */
    private int[] insert(int[] arr) {
        // 从1开始,第一个不要排序,数组从i进行分开
        for (int i = 1; i < arr.length; i++) {
            int data = arr[i];
            // 将数据插入到已经排好序段,从尾往头进行比较,可以降低时间复杂度,即是break
            // j从i-1开始,就是从当前的前一个开始,与当前的数据进行比较
            int j;
            for (j = i - 1; j >= 0; j--) {
                if (arr[j] > data) {
                    arr[j + 1] = arr[j];
                } else {
                    break;
                }
            }
            // 赋值
            arr[j + 1] = data;
        }
        return arr;
    }

    @Test
    public void test() {
        int[] arr = {1, 3, 2, 7, 5};
        int[] newArr = insert(arr);
        System.out.println(Arrays.toString(newArr));
    }

}

 

三:希尔排序

1.思想

  按照几个分段进行排序

  目标就是让更多的数据已经排序好。

 

2.程序

package com.jun.algorithm.foundation.thought;

import org.junit.Test;

import java.util.Arrays;

/**
 * 希尔排序
 * 把记录按照下标进行增量分组,对每一组使用插入排序算法排序
 * 随着增量的减少,每组包含的有序的原来越多,当增量减少为1时,整个文件分为一组,算法终止
 * <p>
 * 稳定性:不稳定
 *
 * @author caojun
 */
public class ShellSort {
    private int[] shell(int[] arr) {
        // 分段
        for (int add = arr.length / 2; add >= 1; add /= 2) {
            for (int i = add; i < arr.length; i++) {
                int data = arr[i];
                int j;
                // 间隔之后,进行前后对比
                for (j = i - add; j >= 0; j -= add) {
                    if (arr[j] > data) {
                        arr[j + add] = arr[j];
                    } else {
                        break;
                    }
                }
                // 赋值
                arr[j + add] = data;
            }

        }
        return arr;
    }

    @Test
    public void test() {
        int[] arr = {1, 3, 2, 7, 5};
        int[] newArr = shell(arr);
        System.out.println(Arrays.toString(newArr));
    }
}

 

 

四:归并排序

1.思路

  将待排序的数组分为两个字数组,分别对它们按同样的方式进行排序,最后将两个有序子数组 归并成一个有序数组。

  

 

 

  

2.程序

package com.jun.algorithm.foundation.thought;

import org.junit.Test;

import java.util.Arrays;

/**
 * 归并排序
 * 递归与分治的思想结合
 * <p>
 * 时间复杂度是nlogn
 * <p>
 * 稳定性:稳定的,因为是对插入排序的优化
 *
 * @author caojun
 */
public class MergeSort {
    /**
     * 排序
     *
     * @param arr   数组
     * @param left  数组的左端
     * @param right 数组的右端
     * @return 排序后的数组
     */
    public int[] merge(int[] arr, int left, int right) {
        // 相等了就表示只有一个数了,不用再分了,终止条件
        if (left < right) {
            int mid = (left + right) / 2;
            merge(arr, left, mid);
            merge(arr, mid + 1, right);
            //
            mergeData(arr, left, mid, right);
        }
        return arr;
    }

    private void mergeData(int[] arr, int left, int mid, int right) {
        // 保存合并后的数据
        int[] temp = new int[arr.length];
        // 左边的第一个数据的位置
        int point1 = left;
        // 右边的第一个数据的位置
        int point2 = mid + 1;
        // 表示已经到达的位置
        int loc = left;

        // 合并的终止条件
        while (point1 <= mid && point2 <= right) {
            if (arr[point1] < arr[point2]) {
                temp[loc] = arr[point1];
                point1++;
                loc++;
            } else {
                temp[loc] = arr[point2];
                point2++;
                loc++;
            }
        }
        // 还有一个数组没有进行将数据合并在,这里是左边没有赋值完
        while (point1 <= mid) {
            temp[loc++] = arr[point1++];
        }
        // 还有一个数组没有进行将数据合并在,这里是右边没有赋值完
        while (point2 <= right) {
            temp[loc++] = arr[point2++];
        }

        // 将临时数组中的数据添加到arr中
        if (right + 1 - left >= 0) {
            System.arraycopy(temp, left, arr, left, right + 1 - left);
        }
    }

    @Test
    public void test() {
        int[] arr = {1, 5, 6, 3, 8};
        int[] newArr = merge(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(newArr));
    }
}

 

五:选择排序

1.思路

  班级找最高的人。

  每次从未排序的区间中找到最小的元素,将其放到已排序区间的末尾,但是不是插入那种方式进行移动数组,选择进行交换。

  

2.程序

package com.jun.algorithm.foundation.thought;

import org.junit.Test;

import java.util.Arrays;

/**
 * 选择排序
 * 使用场景:在班级中选择出身高最高的人
 *
 * 时间复杂度:
 *
 * @author caojun
 */
public class SelectSort {

    public int[] select(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            // 循环的那个就是找到一个最小的
            int min = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[min]) {
                    min = j;
                }
            }
            // 交换
            int temp = arr[min];
            arr[min] = arr[i];
            arr[i] = temp;
        }
        return arr;
    }

    @Test
    public void test() {
        int[] arr = {1, 3, 2, 7, 5};
        int[] newArr = select(arr);
        System.out.println(Arrays.toString(newArr));
    }

}

 

六:冒泡排序

1.思路

  冒泡的方式

  

 

 

 

2.程序

package com.jun.algorithm.foundation.thought;

import org.junit.Test;

import java.util.Arrays;

/**
 * 冒泡排序
 * 每次都和相邻的元素进行比较
 *
 * @author caojun
 */
public class BubbleSort {
    public int[] bubble(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        return arr;
    }

    @Test
    public void test() {
        int[] arr = {1, 3, 2, 7, 5};
        int[] newArr = bubble(arr);
        System.out.println(Arrays.toString(newArr));
    }
}

 

七:快速排序

1.思路

     先分成三个部分,左边,基准数,右边

  然后,分别递归左边与右边的书。

2.程序

package com.jun.algorithm.foundation.thought;

import org.junit.Test;

import java.util.Arrays;

/**
 * 快速排序
 *
 * @author caojun
 */
public class QuickSort {
    /**
     * 排序
     * 每次确定一个中间位置,当每个中间位置都确定return之后,程序也就运行结束了
     *
     * @param arr   数据
     * @param left  左边位置
     * @param right 右边位置
     */
    public void quick(int[] arr, int left, int right) {
        if (left > right) {
            return;
        }
        int base = arr[left];
        int ll = left;
        int rr = right;

        while (ll != rr) {
            // 找到右边比基准数据小的数据
            while (ll < rr && arr[rr] >= base) {
                rr--;
            }
            // 找到左边比基准数据大的数据
            while (ll < rr && arr[ll] <= base) {
                ll++;
            }
            if (ll < rr) {
                int temp = arr[rr];
                arr[rr] = arr[ll];
                arr[ll] = temp;
            }
        }
        // 调整基准点到中间位置,因为后左边查询,所以中间值是ll
        arr[left] = arr[ll];
        arr[ll] = base;
        // 进行下一轮。这个时候,不考虑ll位置数据,因为ll位置已经是正确的了
        quick(arr, left, ll - 1);
        quick(arr, ll + 1, right);
    }

    @Test
    public void test() {
        int[] arr = {1, 3, 2, 7, 5};
        quick(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
}

 

 posted on 2022-04-02 17:09  曹军  阅读(34)  评论(0编辑  收藏  举报