对排序算法做一个总结吧。先提交,回头再补吧
分类
比较类:
- 插入法:
- 插入排序
遍历未排序的列,将遍历到的每个元素插入到有序序列的适当位置。
- 希尔排序。
先将待排序的数组分成若干个子数组排序
- 选择法:包括选择排序和堆排序
- 选择排序
选择第 i 小的元素与第 i- 1 的位置交换
- 交换法:包括冒泡排序和快速排序
非比较类
-
计数排序
-
桶排序
-
基数排序
复杂度和稳定性
不稳定排序口诀:一 堆 希尔 快 选!
1. 插入法
插入排序
public class InsertSort {
public static void main(String[] args) {
int arr[] = {17, 3, 25, 14, 20, 9};
System.out.println("排序前的数组:");
System.out.println(Arrays.toString(arr));
insertSort(arr);
System.out.println("排序后的数组:");
System.out.println(Arrays.toString(arr));
}
public static void insertSort(int arr[]) {
int len = arr.length;
//数组的第一个元素默认有序的,所以从 1 开始遍历
for (int i = 1; i < len; i++) {
int temp = arr[i];
int j = i - 1;
//遍历待排序元素前面的元素,若大于待排序的元素后移一位
while(j >= 0 && arr[j] > temp){
arr[j + 1] = arr[j];
j--;
}
//遍历结束,将待排序的元素插入到所在的位置
arr[j + 1] = temp;//注意是 j + 1
}
}
}
希尔排序
希尔排序:也是一种插入排序
1,把记录按下标的一定增量分组(例如有n个数,先分成n/2组,对每组进行排序。
2,然后分成n/2/2组,进行排序,
3,直到n/2/2...=1,
public class ShellSort {
public static void main(String[] args) {
int arr[] = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void shellSort(int arr[]) {
//第一个for循环是将原数组分组
for (int gap = arr.length / 2; gap > 0 ; gap /= 2) {
//后面同插入排序一样,间隔 1 换成了 gap
for (int i = gap; i < arr.length ; i++) {
int j = i - gap;
int temp =arr[i];
while(j >= 0 && arr[j] > temp) {
arr[j+gap] = arr[j];
j -= gap;
}
arr[j + gap] = temp;
}
}
}
}
选择排序
在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
public class SelectSort {
public static void main(String[] args) {
for (int i = 0; i < arr.length - 1; i++) {
int temp = 0;
int index = i; // 用来保存最小值得索引
// 寻找第i个小的数值
for (int j = i + 1; j < arr.length; j++) {
if (arr[index] > arr[j]) {
index = j;
}
}
// 将找到的第i个小的数值放在第i个位置上
temp = arr[index];
arr[index] = arr[i];
arr[i] = temp;
}
}
}
堆排序
3. 堆的概念
堆是一棵顺序存储的完全二叉树。
完全二叉树
,称为大顶堆;,称为小顶堆。
-
小根堆:或者每个结点的值都小于或等于其左右孩子结点的值。
-
大根堆:每个结点的值都大于或等于其左右孩子结点的值。
同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子:
该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
冒泡排序
它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换
public class BubbleSort {
public static void main(String[] args) {
int arr[] = {17, 3, 25, 14, 20, 9};
System.out.println("排序前的数组:");
System.out.println(Arrays.toString(arr));
bubbleSort(arr);
System.out.println("排序后的数组:");
System.out.println(Arrays.toString(arr));
}
public static void bubbleSort(int arr[]) {
int len = arr.length;
for (int i = 0; i < len - 1; i++) {
for (int j = arr.length - 1; j > i; j--) {
// 比较相邻的元素,如果前面的数大于后面的数,则交换
if (arr[j - 1] > arr[j]) {
int temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
}
}
快速排序
基本思想
1.在待排序的元素任取一个元素作为基准(通常选第一个元素,但最的选择方法是从待排序元素中随机选取一个作为基准),称为基准元素;
2.将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边;
3.对左右两个分区重复以上步骤直到所有元素都是有序的。
- 优化:基准值的选取 选择中间值 int m = low + (high - low) / 2;//数组中间元素的下标
public class QuickSort {
public static void main(String[] args) {
int n = 100000;
Random random = new Random(n);
int[] array = {3,5,4,3,2,1,5,7,4,0};
System.out.println("排序前数组:" + Arrays.toString(array));
quickSort(array,0,array.length - 1);
System.out.println(Arrays.toString(array));
}
//快排的实现
public static void quickSort(int[] arr, int l, int r) {
if(l >= r) return;
int i = l , j = r;
while (i < j) {
while (i < j && arr[j] >= arr[l]) j--;
while (i < j && arr[i] <= arr[l]) i++;
swap(arr, i ,j);
}
swap(arr, i, l);
quickSort(arr, l, i - 1);
quickSort(arr, i + 1, r);
}
//交换数组中的两个元素
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}