1.冒泡排序
分两层循环,外层循环负责循环整个数组,内层循环用来判断相邻两个元素的大小 经过第一遍循环之后,最大的元素已经被放到了最后一位
针对所有的元素进行上面的操作,除了最后一位 直到没有一个元素需要交换,就return
时间复杂度O(n^2) 最优时间复杂度O(n)
最差时间复杂度O(n^2) 空间复杂度O(1)
public void bubbleSort(int[] numbers) {
int tmp;
boolean change = false; // 判断这一轮下来有没有交换
for (int i = 0; i < numbers.length; i++) {
for (int j = 0; j < numbers.length - 1 - i; j++) {
if (numbers[j] > numbers[j + 1]) {
change = true;
tmp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = tmp;
}
}
if (!change) { // 如果没有交换就直接退出
return;
}
}
}
2.选择排序
分两轮循环,第一个循环用来遍历整个数组 第二个循环从i开始,用来比较相邻的两个值的大小
在第二个循环里面,从i 开始,要找到最小值的下标,并跟这轮循环的i交换
时间复杂度O(n^2)
public void selectSort(int[] numbers) {
for (int i = 0; i < numbers.length; i++) {
int minIndex = i;
for (int j = i; j < numbers.length; j++) {
// 获取最小索引数
if (numbers[j] < numbers[minIndex]) {
minIndex = j;
}
}
// 把最小值与i交换
int tmp = numbers[minIndex];
numbers[minIndex] = numbers[i];
numbers[i] = tmp;
}
}
3.插入排序
插入排序 第一位数默认有序,从第二位数开始循环,逐个比较大小,进行排序
如果当前位数的值小于要比较的值,则把被比较的值后移一位,i下标减1,继续向前进行比较 最后找到合适的位置,把当前位数的值放入
时间复杂度:最佳O(n) 最差O(n^2)
public void insertSort(int[] numbers) {
for (int i = 0; i < numbers.length - 1; i++) {
int current = numbers[i + 1];
while (i >= 0 && current < numbers[i]) {
numbers[i + 1] = numbers[i];
i--;
}
numbers[i + 1] = current;
}
}
4.希尔排序
也是一种插入排序
初始增量gap的值为length/2,缩小增量继续以gap =gap/2的方式。 把整个数组分为gap组,对每一组进行插入排序
时间复杂度为O(nlog_2n)
public void shellSort(int[] numbers) {
int gap = numbers.length/2;
while(gap>0){
for (int i = gap; i < numbers.length; i++) {
int preIndex = i-gap;
int tmp = numbers[i];
while(preIndex>=0 && numbers[preIndex]>tmp){
numbers[preIndex+gap] = numbers[preIndex];
preIndex = preIndex - gap;
}
numbers[preIndex+gap] = tmp;
}
gap /= 2;
}
}
5.归并排序
先递归,后合并
* 思路:把无序数组对半进行拆分,拆分的左右两个数组再递归进行拆分,直到最后每个数组只有一个元素。对这两个元素进行排序,排序之后再次进行合并,得到左右两个有序的子数组,最终把两个子数组进行合并。
时间复杂度:最佳O(n) 最差:O(nlogn)
public int[] mergeSort(int[] numbers) {
if (numbers.length < 2)
return numbers;
int mid = numbers.length / 2;
int[] left = Arrays.copyOfRange(numbers, 0, mid);
int[] right = Arrays.copyOfRange(numbers, mid, numbers.length);
return merge(mergeSort(left), mergeSort(right));
}
//合并并排序操作
public int[] merge(int[] left, int[] right) {
int[] result = new int[left.length + right.length]; //
// 声明一个等于左右两个数组长度之和的数组
int i = 0, j = 0;
for (int index = 0; index < result.length; index++) {
if (j >= right.length) {
result[index] = left[i];
i++;
} else if (i >= left.length) {
result[index] = right[j];
j++;
} else if (left[i] > right[j]) { // 如果左边数组的值大于右边对应位的值
result[index] = right[j];
j++;
} else { // 否则,小于等于
result[index] = left[i];
i++;
}
}
return result;
}
6.快速排序
左边指针为i,右边指针为j,初始基准值pivot为第一个元素
从右边j开始进行比较,如果numbers[j]>pivot,则移动指针j,否则,就把numbers[i] = numbers[j], 并把指针i+1,从左边i指针开始比较,同理指针j
时间复杂度:最佳O(nlogn) 最差情况:O(n^2) 平均情况O(nlogn)
public void quickSort(int[] numbers,int left,int right){
int i = left; //从左开始的指针
int j = right; //从右开始的指针
int pivot = numbers[i]; //基准值
while(i<j){
while(numbers[j]>pivot && j>i){ // 如果比基准值大
j--; // 指针继续向左移动
}
if(j>i){
//number[j]是比pivot小的,直接放左边i的位置
numbers[i] = numbers[j];
//并把i指针后移
i++;
while(numbers[i]<pivot && i<j){
i++;
}
if(i<j){
numbers[j] = numbers[i];
j--;
}
}
}
numbers[i] = pivot; // 此时,i,j指针重合
// 递归的对左边进行排序
if(left<(i-1)) quickSort(numbers, left, i-1);
/ 递归的对右边进行排序
if(right>(j+1)) quickSort(numbers, j+1, right);
}