冒泡排序
两两比较,将较小或者较大的值往一侧移动,每次固定一个位置
时间复杂度O(n^2)
空间复杂度:最优O(1)
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
String[] s = {"a", "e", "f", "d", "b", "g", "c"};
BubbleSort.sort(s);
System.out.println(Arrays.toString(s)); //[a, b, c, d, e, f, g]
}
public static void sort(String[] s) {
//冒泡排序,外循环,将第i小的值放到i位置,
for (int i = 0; i < s.length - 1; i++)
//内循环,从后向前两两比较,小的置前
for (int j = s.length - 1; j > i ; j--) {
if (s[j - 1].compareTo(s[j]) > 0) {
String temp = s[j - 1];
s[j - 1] = s[j];
s[j] = temp;
}
}
}
}
选择排序
查找最小值位置,前移,每次固定一个位置
时间复杂度O(n^2)
空间复杂度O(1)
public static void selectSort(String[] s){
for(int i = 0; i < s.length - 1; i++){
int minIndex = i; //外循环,将第i小的值固定到此
//内循环查找最小值位置
for(int j = i + 1; j < s.length ; j++){
if(s[j].compareTo(s[minIndex]) < 0)
minIndex = j;
}
if(minIndex != i){
String temp = s[i];
s[i] = s[minIndex];
s[minIndex] = temp;
}
}
}
插入排序
类似抓扑克牌,前面的牌大就后移,找到正确的位置插入新抓的牌
时间复杂度O(n^2)
空间复杂度O(1)
public static void insertSort(String[] s){
for (int i = 1; i < s.length; i++){
//默认第一个位置是正确的
//待插入元素
String target = s[i];
int j = i;
//向前依次比较,较大的后移,找到正确的插入位置j
while(j > 0 && target.compareTo(s[j-1]) < 0){
s[j] = s[j-1];
j--;
}
s[j] = target;
}
}
快速排序
时间复杂度O(nlogn),最差情况等同插入排序O(n^2)
import java.util.Arrays;
public class QuickSort {
private int[] arr;
public QuickSort(int[] arr){
this.arr = arr;
}
/*分治
将所有比arr[i]小的移到左边,比arr[i]大的移到右边,返回移动后位置p
将数组拆成两半,递归子问题[i,p-1]、[p+1,j]
*/
private int partition(int i,int j){
if(i==j)
return i;
int p = i/2;
int target = arr[p];
while(i < j){
while(arr[i] < target && i < j)
i++;
arr[p] = arr[i];
p=i;
while(arr[j] > target && i < j)
j--;
arr[p] = arr[j];
p=j;
}
arr[p] = target;
return p;
}
public void sort(){
recursion(0,arr.length-1);
}
//递归
private void recursion(int i, int j){
int p = partition(i,j);
if(p>i)
recursion(i, p - 1);
if(p<j)
recursion(p + 1, j);
}
public static void main(String[] args) {
int[] arr = {4,5,3,1,6,9,0};
new QuickSort(arr).sort();
System.out.println(Arrays.toString(arr));
}
}
堆排序
用二叉树代表数组,升序则构建大顶堆,降序则构建小顶堆
对于数组元素arr[i],其左右孩子是arr[2*i+1]和arr[2*i+2]
时间复杂度O(nlogn)
import java.util.Arrays;
public class HeapSort {
//构建大顶堆
private static void buildMaxHeap(int[] arr){
for(int i = arr.length / 2 - 1; i >= 0; i--)//从底层开始遍历
recursion(arr,i,arr.length-1);
}
//递归,当前节点和左右孩子比较,孩子中有最大值则上移,当前节点下移,然后向下递归
private static void recursion(int[] arr,int i,int last){
int left = 2 * i + 1;
int right = 2 * i + 2;
int max = i;
if(left > last)
return;
else if(right > last){
if(arr[left] > arr[i])
max = left;
}else {
if(arr[left] > arr[right] && arr[left] > arr[i])
max = left;
if(arr[left] <= arr[right] && arr[right] > arr[i])
max = right;
}
if(max != i){
exchange(arr,i,max);
recursion(arr,max,last);
}
}
//交换
private static void exchange(int[] arr,int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
private static void sort(int[] arr){
if(arr==null || arr.length==0)
return;
buildMaxHeap(arr);//构建大顶堆
//升序,依次将堆顶和堆尾交换
for(int i = arr.length-1; i > 0;i--){
exchange(arr,0,i);
recursion(arr,0,i-1);//构建[0,i-1]的大顶堆
}
}
public static void main(String[] args) {
int[] arr = {3,6,7,4,1,8,2};
HeapSort.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
Shell排序
设置增量,对等差数列位置的元素进行插入排序,循环缩小增量,最后进行一次全量的插入排序
public class ShellSort {
public static void sort(int[] arr){
if(arr == null || arr.length == 0)
return;
int d = arr.length / 2;
while(d > 0){
subSort(arr,d);
d /= 2;
}
}
public static void subSort(int[] arr,int d){
for(int i = d; i < arr.length; i = i + d){
int tmp = arr[i];
int j = i - d;
for(; j >=0 && arr[j] > tmp; j = j - d){
arr[j+d] = arr[j];
}
if(j!=i-d){
arr[j+d] = tmp;
}
}
}
public static void main(String[] args) {
int[] arr = {6,4,8,5,3,7,2};
ShellSort.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
归并排序
拆分成易于解决的子集,然后将子集合并
public class MergeSort {
public static void sort(int[] arr){
recursion(arr,0,arr.length-1);
}
public static void recursion(int[] arr, int start, int end){
if(start>=end) //最终只有一个元素退出
return;
int mid = ( start + end ) / 2;//从中间拆分递归
recursion(arr,start,mid);
recursion(arr,mid + 1,end);
merge(arr,start,end,mid);//子数组合并排序
}
public static void merge(int[] arr, int start, int end, int mid){
int[] tmp = new int[end - start + 1];
int k = 0;
int i = start;
int j = mid + 1;
while(i<=mid && j<=end){
if(arr[i]<=arr[j])
tmp[k++] = arr[i++];
else
tmp[k++] = arr[j++];
}
while(i<=mid)
tmp[k++]=arr[i++];
while(j<=end)
tmp[k++]=arr[j++];
for(k=0;k<tmp.length;k++)
arr[start+k]=tmp[k];
}
public static void main(String[] args) {
int[] arr = {6,4,8,5,3,7,2};
MergeSort.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
其他
计数排序:将数据作为数组下标,数据量过大时不建议使用
桶排序:通过映射函数将数据映射到不同桶中,再对桶中数据进行排序,是计数排序的优化