一、快排
public class 快速排序 {
/**性质:1、时间复杂度:O(nlogn) 2、空间复杂度:O(logn) 3、非稳定排序 4、原地排序*/
public static void main(String[] args) {
int[] num = {64,55,3,266,232,66,44};
quickSort(num,0,num.length-1);
for (int i = 0; i < num.length; i++) {
System.out.println(num[i]);
}
}
public static int[] quickSort(int[] arr, int left, int right) {
if (left < right) {
//获取中轴元素所处的位置
int mid = partition(arr, left, right);
//进行分割
arr = quickSort(arr, left, mid - 1);
arr = quickSort(arr, mid + 1, right);
}
return arr;
}
private static int partition(int[] arr, int left, int right) {
//选取中轴元素
int pivot = arr[left];
int i = left + 1;
int j = right;
while (true) {
// 向右找到第一个小于等于 pivot 的元素位置
while (i <= j && arr[i] <= pivot) {
i++;
}
// 向左找到第一个大于等于 pivot 的元素位置
while(i <= j && arr[j] >= pivot ){
j--;
}
if(i >= j)
break;
//交换两个元素的位置,使得左边的元素不大于pivot,右边的不小于pivot
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
arr[left] = arr[j];
// 使中轴元素处于有序的位置
arr[j] = pivot;
return j;
}
}
![](https://img2018.cnblogs.com/blog/1415794/201907/1415794-20190731204419345-1550488828.png)
二、冒泡排序
public class 冒泡排序优化 {
public static void main(String[] args) {
int[] num = {64,65,67,66,68,69,70};
bubbleSort(num);
for (int i = 0; i < num.length; i++) {
System.out.println(num[i]);
}
}
public static int[] bubbleSort(int[] arr) {
if (arr == null || arr.length < 2) {
return arr;
}
int n = arr.length;
for (int i = 0; i < n; i++) {
boolean flag = true;
for (int j = 0; j < n -i - 1; j++) {
if (arr[j + 1] < arr[j]) {
flag = false;
int t = arr[j];
arr[j] = arr[j+1];
arr[j+1] = t;
}
}
//一趟下来是否发生位置交换
if(flag)
break;
}
return arr;
}
}
三、选择排序
public class 选择排序 {
/**
* 首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。
* 其次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。这种方法我们称之为选择排序。
* 性质:1、时间复杂度:O(n2) 2、空间复杂度:O(1) 3、非稳定排序 4、原地排序*/
public static void main(String[] args) {
int[] num = {64,55,3,266,232,66,44};
selectSort(num);
for (int i = 0; i < num.length; i++) {
System.out.println(num[i]);
}
}
/**
* 首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置
(如果第一个元素就是最小元素那么它就和自己交换)。
* 其次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。
如此往复,直到将整个数组排序。这种方法我们称之为选择排序。
* 性质:1、时间复杂度:O(n2) 2、空间复杂度:O(1) 3、非稳定排序 4、原地排序*/
public static int[] selectSort(int[] a) {
int n = a.length;
for (int i = 0; i < n - 1; i++) {
int min = i;
for (int j = i + 1; j < n; j++) {
if(a[min] > a[j]) {
min = j;
}
}
//交换
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
return a;
}
/**
1、稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 仍然在 b 的前面,则为稳定排序。
2、非稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 可能不在 b 的前面,则为非稳定排序。
3、原地排序:原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。
4、非原地排序:需要利用额外的数组来辅助排序。
5、时间复杂度:一个算法执行所消耗的时间。
6、空间复杂度:运行完一个算法所需的内存大小。
*/
}
四、归并排序
public class 归并排序 {
/**性质:1、时间复杂度:O(nlogn) 2、空间复杂度:O(n) 3、稳定排序 4、非原地排序*/
public static void main(String[] args) {
int[] num = {64,55,3,266,232,66,44};
mergeSort(num,0,num.length-1);
for (int i = 0; i < num.length; i++) {
System.out.println(num[i]);
}
}
// 归并排序
public static int[] mergeSort(int[] arr, int left, int right) {
// 如果 left == right,表示数组只有一个元素,则不用递归排序
if (left < right) {
// 把大的数组分隔成两个数组
int mid = (left + right) / 2;
// 对左半部分进行排序
arr = mergeSort(arr, left, mid);
// 对右半部分进行排序
arr = mergeSort(arr, mid + 1, right);
//进行合并
merge(arr, left, mid, right);
}
return arr;
}
// 合并函数,把两个有序的数组合并起来
// arr[left..mif]表示一个数组,arr[mid+1 .. right]表示一个数组
public static void merge(int[] arr, int left, int mid, int right) {
//先用一个临时数组把他们合并汇总起来
int[] a = new int[right - left + 1];
int i = left;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= right) {
if (arr[i] < arr[j]) {
a[k++] = arr[i++];
} else {
a[k++] = arr[j++];
}
}
while(i <= mid) a[k++] = arr[i++];
while(j <= right) a[k++] = arr[j++];
// 把临时数组复制到原数组
for (i = 0; i < k; i++) {
arr[left++] = a[i];
}
}
}