常用排序算法
1、冒泡排序
时间复杂度:O(n^2)
思路:双层循环
- 比较相邻两个数的大小,把小的放到左边
- 每次循环,都会产生一个最大或最小的数
- 下一次循环可少排序一次
// 冒泡排序
public static void sort1(int[] arr){
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-1-i; j++) {
int mid;
if (arr[j] > arr[j+1]){
mid = arr[j];
arr[j] = arr[j+1];
arr[j+1] = mid;
}
}
}
System.out.println(Arrays.toString(arr));
}
2、选择排序
时间复杂度:O(n^2)
思路:
- 双层循环
- 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾
// 选择排序
public static void sort2(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;
}
}
if (i != min){
int mid = arr[i];
arr[i] = arr[min];
arr[min] = mid;
}
}
System.out.println(Arrays.toString(arr));
}
3、插入排序
时间复杂度:O(n^2)
思路:
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。
如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。
// 插入排序
public static void sort3(int[] arr){
int num;
for (int i = 1; i < arr.length; i++) {
num = arr[i]; // 记录要插入的数
int j = i;
// 从已经排序的序列最右边的开始比较,找到比其小的数
while (j > 0 && arr[j-1] > num){
arr[j] = arr[j-1];
j--;
}
// 存在比其小的则插入
if (i != j) arr[j] = num;
}
System.out.println(Arrays.toString(arr));
}
4、快速排序
时间复杂度:O(n*logn)
思路:
- 从数列中挑出一个元素,称为 “基准”(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边);
- 在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
// 快速排序
public static void sort4(int[] arr, int left, int right){
if (left < right){
int i = GetIndex(arr, left, right);
sort4(arr, left, i-1);
sort4(arr, i+1, right);
}
}
private static int GetIndex(int[] arr, int left, int right) {
int l = left, r = right;
int pivot = arr[l];
while (l<r){
// 从右往左遍历,找到比基准小的值
while (l<r && arr[r]>pivot)
r--;
// 将这个值放入空坑位
if (l<r){
arr[l] = arr[r];
l++;
}
// 从左往右遍历,找出比基准大的值
while (l<r && arr[l]<pivot)
l++;
// 将这个值放入空坑位
if (l<r){
arr[r] = arr[l];
r--;
}
}
arr[l] = pivot;
return l;
}