冒泡排序
主要思想:是首先将一个一个挨着比较,将最大的放在后面,每一次遍历,都保证最后一个值最大。
public static void bubbleSort(int[] arr){
//冒泡排序
int len=arr.length;
for(int i=1;i<len;i++){
for(int j=0;j<len-i;j++){
if(arr[j]>arr[j+1]){
swap(arr,j,j+1);
}
}
}
}
插入排序
主要思想:将未排序的元素,逐个插入到已排序的里面
每次检索下个元素n,前面0到n-1的元素都已排好序,要做的是,将n插入到已排好序的里面
public static void insertSort(int[] array){
//插入排序
int i,j,temp;
for(i=1;i<array.length;i++) {
temp=array[i];
for(j=i-1;j>=0;j--) {
if(temp>array[j]) {
break;
}else {
array[j+1]=array[j];
}
}
array[j+1]=temp;
}
}
选择排序
主要思想:每次令i为最小值的下标,然后去循环后面元素(因为前面i-1个元素都已排好序),找到剩下元素的最小值下标,拿到了当前i和最小值下标,就进行交换,具有不稳定性。
public static void selectSort(int[] arr){
//选择排序
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[min]){
min = j;
}
}
if(min!=i){
swap(arr, i, min);
}
}
}
快速排序(分治思想)
主要思想,简单来说就是随意设定一个基础值base,然后小于base的放左边,大于base的放右边,分成的两个部分,也用同样思想,都取出一个新的base,小的放左边,大的放右边,最后放下去,就会排好序了。
其中关键点,给一个数组进行快排,都使用双游标left和right,左++,右–,遍历完所有元素,使其可以小的放左,大的放右,具体实现回顾,参考代码,自己手写,每次回顾一定快速记住。
public static void quikSort(int[] arr,int left,int right){
//快速排序(分治思想)
if(right<=left)return;
int k=part(arr,left,right);
quikSort(arr,left,k-1);
quikSort(arr,k+1,right);
}
private static int part(int[] arr, int left, int right) {
int base=arr[left];
while (left<right){
//右边开始
for(;arr[right]>base&&right>left;right--);
if(right>left){
arr[left]=arr[right];
left++;
}
//左边
for(;arr[left]<base&&right>left;left++);
if(left<right){
arr[right]=arr[left];
right--;
}
}
arr[left]=base;
return left;
}
归并排序
主要思想,是一直一直一分为二,直到分不开的时候,开始合并,每次合并都借助于一个新的数组temp,来存放合并且排好序的,然后将temp赋值给元素组其中合并的那一段,然后一段一段的赋上去,排序成功。
代码主要理解在于,合并的时候,其实数组a并没有拆开,只是理解上它被一分为二,然后使用(low,mid)(mid+1,high)将其分为两段来理解,然后设定双游标为i=low和j=mid+1;让他俩去取a中的元素做比较,然后赋值给Temp,就合并好一小段,总的来看,就成功了(理解理解!!)
public static int[] sort(int[] a,int low,int high){
int mid = (low+high)/2;
if(low<high){
sort(a,low,mid);
sort(a,mid+1,high);
//左右归并
merge(a,low,mid,high);
}
return a;
}
public static void merge(int[] a, int low, int mid, int high) {
int[] temp = new int[high-low+1];
int i= low;
int j = mid+1;
int k=0;
// 把较小的数先移到新数组中
while(i<=mid && j<=high){
if(a[i]<a[j]){
temp[k++] = a[i++];
}else{
temp[k++] = a[j++];
}
}
// 把左边剩余的数移入数组
while(i<=mid){
temp[k++] = a[i++];
}
// 把右边边剩余的数移入数组
while(j<=high){
temp[k++] = a[j++];
}
// 把新数组中的数覆盖nums数组
for(int x=0;x<temp.length;x++){
a[x+low] = temp[x];
}
}
堆排序
主要思想,首先弄懂二叉树基本定义
parent(i)=(i-1)/2
left_child(i)=2i+1
right_child(i)=2i+1;理解不到这三条就不用看了
可以推导出性质:
最后一个叶子节点(没有子节点叫叶子节点)的索引为arr.length-1 。
最后一个非叶子节点索引为 (arr.lenght-1-1)/2
先看算法动画:
http://www.cs.usfca.edu/~galles/visualization/HeapSort.html
剩下算法参考:
https://blog.csdn.net/nrsc272420199/article/details/82559912
写的十分详细,简单易理解。
总的来说无非三点:
1.构造二叉树,由数组构成大根堆(父节点大于左右两个子节点),又叫做heapify
2.树的头节点就是最大数,将这个堆顶的数和堆底(最后一位)交换位置
3.重复步骤,一步一步将当前最大值从右往左排列出来
难点,大根堆原理和算法实现,参考上面引用博客吧,写的太好了。