- 冒泡排序
1.思路:遍历所有数每一轮通过交换把最大的数挪到最后。
2.最差、平均、复杂度都是O(n²),最好是O(n)。
static void bubbleSort(int[] A) {
for(int n=A.length-1;n>=0;n--){
for(int i=0;i<n;i++){
if(A[i]>A[i+1]){
int temp=A[i];
A[i]=A[i+1];
A[i+1]=temp;
}
}
}
}
- 选择排序
1.思路:从前面开始放 每一轮选出一个最小的记录其下标 在和前面未排序的数交换。
2.最差、平均、最好复杂度都是O(n²)。
static void selectSort(int[] A) {
for (int i = 0; i < A.length; i++) {
int minIndex = i;
int min = A[i];
for (int j = i; j < A.length; j++) {
if (A[j] < min) {
minIndex = j;
}
}
int temp = A[i];
A[i]=A[minIndex];
A[minIndex]=temp;
}
}
- 插入排序
1.思路:通过插入保证当前遍历的数前面那一段有序(包括当前的数)
2.比如 3,4,5,2,6,7 当前遍历的数为2, 2和前面所有的数比较(2前面的数往前挪)把2放到合适的位置。
2.最差、平均、复杂度都是O(n²),最好是O(n)。
static void insertSort(int[] A) {
for (int i = 1; i < A.length; i++) {
if (A[i] < A[i - 1]) {
int temp = A[i];
int j;
for (j = i - 1; j >= 0 && temp < A[j]; j--) {
A[j + 1] = A[j];
}
A[j + 1] = temp;
}
}
}
- 思路 分组插入排序 按一定的增量分组
选gap=A.length/2 增量序列{n/2,(n/2)/2…1} - 平均时间复杂度O(nlogn) 其他好的增量序列效率会提高。
static void shellSort(int[] A) {
for (int d = A.length / 2; d > 0; d /= 2) {
for (int i = d; i < A.length; i++) {
for (int j = i - d; j >= 0; j -= d) {
if (A[j] > A[j + d]) {
int temp = A[j + d];
A[j + d] = A[j];
A[j] = temp;
}
}
}
}
}
- 分治法(用递归实现)定义一个基数 基数左边的比基数小
基数右边的比基数大,分别对左边和右边排序。 - 时间复杂度O(nlogn)最坏的情况相当于冒泡排序O(n²)每一次取到的不是靠中间的值。
public static void quick(int[] arr,int low,int high) {
if(low<high) {
int q=partition2(arr,low,high);
quick(arr,low,q-1);
quick(arr,q+1,high);
}
}
public static int partition2(int[] arr,int low,int high) {
int stard=arr[low];
int p=low+1;
int q=high;
while(p<=q) {
while(p<=q&&arr[p]<=stard)p++;
while(p<=q&&arr[q]>=stard)q--;
if(p<q) {
int temp=arr[p];
arr[p]=arr[q];
arr[q]=temp;
}
}
int temp=arr[q];
arr[q]=stard;
arr[low]=temp;
return q;
}
public static int partition(int[] arr, int low, int high) {
int stard=arr[low];
int p=low+1;
int q=high;
while(p<=q) {
if(arr[p]<=stard) {
p++;
}else {
int temp=arr[p];
arr[p]=arr[q];
arr[q]=temp;
q--;
}
}
int temp=arr[q];
arr[q]=stard;
arr[low]=temp;
return q;
}
- 归并排序
1.利用分治的思想 将问题分解成一些小的问题递归求解
2.在将分阶段得到的答案合并在一起
3.最坏,平均,最好时间复杂度O(nlogn)。
static void mergeSort(int[] A, int low, int high) {
if (low < high) {
int mid = low + ((high - low) >> 1);
mergeSort(A, low, mid);
mergeSort(A, mid + 1, high);
merge(A, low, mid, high);
}
}
static void merge(int[] A, int low, int mid, int high) {
int[] helper=new int[A.length];
System.arraycopy(A, low, helper, low, high - low + 1);
int left = low;
int right = mid+1;
int current = low;
while (left <= mid && right <= high) {
if (helper[left] <= helper[right]) {
A[current] = helper[left];
left++;
current++;
} else {
A[current] = helper[right];
right++;
current++;
}
}
while (left <= mid) {
A[current] = helper[left];
left++;
current++;
}
while(right<=high) {
A[current] = helper[right];
current++;
right++;
}
}
- 堆排序
1.利用堆这种数据结构,是一种选择排序,先构造成一个大顶堆或者小顶推(逆序)。
3.最坏,平均,最好时间复杂度O(nlogn)。
static void MinHeap(int[] A){
int n=A.length;
for (int i=(n-1)/2;i>=0;i--){
MinHeapFixDown(A,i,n);
}
}
static void MinHeapFixDown(int[] A,int i,int n){
int left=2*i+1;
int right=2*i+2;
if(left>=n) return;
int min=left;
if(right<n&&A[right]<A[left])
min=right;
if(A[i]<=A[min])return;
int temp=A[i];
A[i]=A[min];
A[min]=temp;
MinHeapFixDown(A,min,n);
}
static void sort(int[] A,int n){
MinHeap(A);
for(int x=n-1;x>=0;x--) {
int temp=A[x];
A[x]=A[0];
A[0]=temp;
MinHeapFixDown(A,0,x);
}
}
- 计数排序
1.用辅助数组的下标来记录原数组中的值以达到空间换时间
2.时间复杂度O(n+k)。
public static int[] getRandomArr(int length, int min, int max) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * (max + 1 - min) + min);
}
return arr;
}
public static void main(String[] args) {
int[] arr=getRandomArr(4,1,10);
System.out.println(Arrays.toString(arr));
countSort(arr);
System.out.println(Arrays.toString(arr));
}
static void countSort(int[] A){
int max=A[0];
for(int x:A){
if(x>max)
max=x;
}
int[] helper=new int[max+1];
for(int x:A){
helper[x]++;
}
int index=0;
for(int i=0;i<helper.length;i++){
while (helper[i] > 0) {
A[index++] = i;
helper[i]--;
}
}
}