数组中两个数交换位置:
public static void swap(int[] arr, int a, int b){
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
一、基于比较的排序
1、冒泡排序
public static void bubbleSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
for(int end = arr.length-1;end > 0;end--){
for(int i = 0; i < end; i++){
if(arr[i] > arr[i+1]){
swap(arr, i, i+1);
}
}
}
}
前后两个数比较,每一轮都将最大的数移到(未排数据)最后。
时间复杂度:O(n^2)
空间复杂度:O(1)
2、选择排序
public static void selectionSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
for(int i = 0;i < arr.length-1;i++){
int min = i;
for(int j = i; j < arr.length;j++){
min = arr[j] < arr[min] ? j:min;
}
swap(arr, min, i);
}
}
将最小数放在前边,每次都是找出后边最小的数放在当前位置
时间复杂度:O(n^2)
空间复杂度:O(1)
3、插入排序
public static void insertSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
for(int i = 0; i < arr.length-1; i++){
for(int j = i+1; j>0 && arr[j] < arr[j-1]; j--){
swap(arr, j, j-1);
}
}
}
依次将数据插入到已经排好的数据中,当前数(n)小于前边的数(n-1)则交换,一直往前比较。
时间复杂度:O(n^2)
空间复杂度:O(1)
4、归并排序
public static void mergeSort(int[] arr, int l, int r){
if(arr == null || arr.length < 2){
return;
}
if(l == r){
return;
}
int mid = (l + r)/2;
mergeSort(arr, l, mid);
mergeSort(arr, mid+1, r);
merge(arr, l, mid, r);
}
public static void merge(int[] arr, int l,int mid, int r){
int[] temp = new int[r-l+1];
int a = l;
int b = mid+1;
int index = 0;
while(index <= r-l){
if(a <= mid && b <= r){
temp[index++] = arr[a] <= arr[b]?arr[a++]:arr[b++];
}else if(a > mid){
temp[index++] = arr[b++];
}else {
temp[index++] = arr[a++];
}
}
for(int i = 0; i < temp.length; i++){
arr[l++] = temp[i];
}
}
递归分治,通过外排排序(生成一个数组,通过双指针的方法将两部分排序合并)
时间复杂度:O(n*logn)
空间复杂度:O(n)
5、快排
public static void quickSort(int[] arr, int l, int r){
if(r < l){
return;
}
int num = arr[r];
int a = l;
int b = r;
int cur = l;
while(cur <= b){
if(arr[cur] < num){
swap(arr, a++, cur++);
}else if(arr[cur] > num){
swap(arr, b--, cur);
}else{
cur++;
}
}
quickSort(arr, l, --a);
quickSort(arr, ++b, r);
}
每次都将小于最后一个数的放在左边,大于最后一个数的放在右边,等于的放在中间。然后递归,因为等于的放中间,所以直到r<l 递归才能返回。
时间复杂度:O(n*logn)
空间复杂度:O(1)
6、堆排
public static void heapSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
heapInsert(arr, i);
}
int heapSize = arr.length;
while (heapSize > 1) {
swap(arr, 0, --heapSize);
heapFry(arr, 0, heapSize);
}
}
public static void heapInsert(int[] arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
public static void heapFry(int[] arr, int index, int heapSize) {
int left = 2 * index + 1;
while (left < heapSize) {
int Largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
Largest = arr[index] > arr[Largest] ? index : Largest;
if (Largest == index) {
return;
}
swap(arr, Largest, index);
index = Largest;
left = 2 * index + 1;
}
}
将数组看成堆,heapInsert() 方法将 数组排成大根堆(跟节点比叶子节点都大)的形式,heapFry()方法将根节点与最后的叶子节点交换(也就是数组第一个数和最后一个数)。遍历一便。
时间复杂度:O(n*logn)
空间复杂度:O(1)
选择排序不平稳例子: 5 8 5 2 。 第一个5必定要和2交换位置。
堆排序不平稳例子: 3 9 5 9。 第一个3会和后边的9交换位置。
快排不平稳: 4 4 3 。 大于3的放右边,首先第一个4会和3交换位置。
只要不是通过相邻两数比较进行排序的,都不具备平稳性。
二、不是基于比较的排序
桶排序,基数排序,计数排序
时间复杂度:O(n)
空间复杂度:O(n)