目录
一、插入排序
1、直接插入排序
它的算法思想是:把要排序的数组分为了两个部分, 一部分是数组的全部元素(除去待插入的元素), 另一部分是待插入的元素; 先将第一部分排序完成, 然后再插入这个元素. 其中第一部分的排序也是通过再次拆分为两部分来进行的。
在这里默认arr[0]是排完序的那部分,arr[j] = arr[j - 1];表示如果当前要排序的数比从后向前遍历的数小,那么就向后移, arr[j] = temp;表示在对应的位置插入数值。
int[] arr = {1,4,2,8,74,12,9,30,8,11,22,87,12,44,28};
int gap = 1,i,j;
int temp;
int len = arr.length;
for(i = 1;i < len;i++){
temp = arr[i];
for(j = i;j >= 1&&arr[j - 1] > temp;j -= 1){
arr[j] = arr[j - 1];
}
arr[j] = temp;
}
平均时间复杂度 |
最好情况 |
最坏情况 |
空间复杂度 |
O(n²) |
O(n) |
O(n²) |
O(1) |
2、希尔排序
将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次再将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。)
实际上,直接插入排序是把步长为1的两个值进行比较,而希尔排序是将步长表示成了gap。这是对直接插入排序的一种优化。
int[] arr = {1,4,2,8,74,12,9,30,8,11,22,87,12,44,28};
int gap = 1,i,j;
int temp;
int len = arr.length;
while(gap < len /3){
gap = gap * 3 + 1;
}
for(;gap > 0; gap /= 3){
for(i = gap ; i < len;i++){
temp = arr[i];
for(j = i;j >= gap && arr[j - gap]> temp;j -= gap){
arr[j] = arr[j - gap];
}
arr[j] = temp;
}
}
平均时间复杂度 |
最好情况 |
最坏情况 |
空间复杂度 |
O(nlog2 n) |
O(nlog2 n) |
O(nlog2 n) |
O(1) |
二、选择排序
1、简单选择排序
这个算法比较简单,就是每次找到最小的数值,然后保存他的下标与前面第1、2.....arr.length-1交换。
int[] arr = {1,4,2,8,74,12,9,30,8,11,22,87,12,44,28};
for(int i = 0;i < arr.length - 1;i++){
int min = i;
for(int j = i + 1;j < arr.length;j++){
if(arr[j] < arr[i]){
min = j;
}
}
if(min != i){
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
O(n²) |
O(n²) |
O(n²) |
O(1) |
2、堆排序
首先先将数组转换成堆,这里是大顶堆。然后通过遍历每次取大顶堆堆顶元素,再重新heapify。完成排序。
public static void main(String[] args) {
// int[] arr = {1,4,2,8,74,12,9,30,8,11,22,87,12,44,28};
int[] arr = {2,5,3,1,10,4};
heap_sort(arr,arr.length);
for(int k = 0;k < arr.length;k++){
System.out.print(arr[k] + " ");
}
}
//通过堆排序,输出
public static void heap_sort(int[] arr,int len){
build_heapify(arr,len);
for(int i = len - 1;i >= 0; i--){
swap(arr,i,0);
heapify(arr,i,0);
}
}
//构建整个堆,每一个堆节点
public static void build_heapify(int[] arr,int len){
int last_node_index = len - 1;
int parent_index = (last_node_index - 1) / 2;
for(int i = parent_index;i >= 0;i--){
heapify(arr,len,i);
}
}
//对单个堆进行排序
public static void heapify(int []arr,int len,int i){
if(i >= len)
return ;
int left = i * 2 + 1;
int right = i * 2 + 2;
int max = i;
if(left < len && arr[max] < arr[left])
max = left;
if(right < len &&arr[max] < arr[right])
max = right;
if(max != i){
swap(arr,max,i);
heapify(arr,len,max);
}
}
public static void swap(int[] arr,int x,int y){
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
平均时间复杂度 |
最好情况 |
最坏情况 |
空间复杂度 |
O(nlog2n) |
O(nlog2n) |
O(nlog2n) |
O(1) |
三、交换排序
1、冒泡排序
这个算法也比较简单,直接将最大值冒泡到最后一个位置。
for(int i = arr.length;i >= 0;i--){
for(int j = 0;j < i&& j + 1 < i;j++){
if (arr[j] > arr[j + 1]){
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
平均时间复杂度 |
最好情况 |
最坏情况 |
空间复杂度 |
O(n²) |
O(n) |
O(n²) |
O(1) |
2、快速排序
快速排序是对冒泡排序的一种优化,这个算法的思想是:选定一个基准值,使这个基准值的左边都是小于它,右边都是大于它的值。
public static void quick_sort(int[] arr ,int low,int high){
if(arr.length < 0 || low > high)
return ;
int left = low;
int right = high;
//保存基准值
int temp = arr[left];
while(left < right){
//从后向前找到比基准小的元素
while(left < right && arr[right] >= temp){
right--;
}
arr[left] = arr[right];
//从前往后找到比基准大的元素
while(left < right && arr[left] <= temp){
left++;
}
arr[right] = arr[left];
}
arr[left] = temp;
quick_sort(arr,low,left - 1);
quick_sort(arr,left + 1,high);
}
O(nlog₂n) |
O(nlog₂n) |
O(n²) |
O(1)(原地分区递归版) |
四、归并排序
思想:
①. 将序列每相邻两个数字进行归并操作,形成 floor(n/2)个序列,排序后每个序列包含两个元素;
②. 将上述序列再次归并,形成 floor(n/4)个序列,每个序列包含四个元素;
③. 重复步骤②,直到所有元素排序完毕。
public static int[] mergingSort(int[] arr){
if(arr.length <= 1)
return arr;
int num = arr.length >> 1;
int[] arrLeft = Arrays.copyOfRange(arr,0,num);
int[] arrRight = Arrays.copyOfRange(arr,num,arr.length);
return mergeTwoArray(mergingSort(arrLeft),mergingSort(arrRight));
}
public static int[] mergeTwoArray(int[] arr1,int[] arr2){
int[] result = new int[arr1.length + arr2.length];
int i = 0,j = 0, k = 0;
while(i < arr1.length && j < arr2.length){
if(arr1[i] < arr2[j]){
result[k++] = arr1[i++];
}else{
result[k++] = arr2[j++];
}
}
while(i < arr1.length){
result[k++] = arr1[i++];
}
while(j < arr2.length){
result[k++] = arr2[j++];
}
return result;
}
五、基数排序
利用桶排序的思想
public static void radixSort(int[] arrays){
int max = findMax(arrays);
//遍历位数
for(int i = 1;max / i > 0;i *= 10){
int[][] buckets = new int[arrays.length][10];
//获取每一位数字(个、十、百、千位...分配到桶子里)
for(int j = 0;j < arrays.length;j++){
int num = (arrays[j] / i) % 10;
//将其放入桶子里
buckets[j][num] = arrays[j];
}
//回收桶子里的元素
int k = 0;
for(int j = 0;j < 10;j++){
for(int y = 0;y < arrays.length;y++){
if(buckets[y][j]!=0){
arrays[k++] = buckets[y][j];
}
}
}
}
}
public static int findMax(int[] arrays){
int max = 0;
for(int i = 0;i < arrays.length;i++){
if(arrays[i] > max){
max =arrays[i];
}
}
return max;
}