时间复杂度为O(n^2) , 空间复杂度为O(n)
比较基础的遍历啦 思想是很容易的 , 将数组先遍历一遍(0 ~ length-1)找到最小的的值,将他放在第一位(索引为0), 继续交换剩余数组(1 ~ length -1) 将他和第二个数进行交换(索引为1)一直到条件不满足。
文字描述文化有限,我们来看看代码:
for(int i = 0 ; i < arr.length - 1 ; i++){ // 0 ~ n-1
int minNum = arr[i];
for(int j = i + 1 ; j < arr.length ; j++){ // i ~ n-1上找最小的值
int minNum = arr[i] < arr[j] ? i : j;
}
int temp = arr[i];
arr[i] = arr[minNum];
arr[minNum] = temp;
}
人话来说 就是挑最小值放在第一个 , 然后剩余的数挑一个最小的放在第二个…
最终完成排序。
简单吧!!
下面这个也很简单,和选择排序有点像 都是 时间复杂度为 O(n^2) 空间复杂度为 O(1);
每一次比较将相邻的数进行比较将大的往后交换 , 就会在最后一位得到最大值 将剩下的继续进行比较,倒数第二个数就是最大的。依次类推得到排序好的数组啦
代码如下
for(int i = 0 ; i < arr.length -1 ; i++){ //0 ~ n-1
for(int j = 0 ; j < arr.length - 1 - i ; j++){ // 0 ~ n-1-i (每次范围缩小1个)
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
还是很简单的吧~~
这会比上面两个排序好一点的排序,还是不算难
插入排序如同他的名字。
想象一下,你有一把的牌, 你要把他从小到大进行排序 首先你要保证第1张牌之前是整齐的(这不是废话吗,就1张。。。纯纯哥谭噩梦)然后呢,你就要保证前两张牌是排好序的(如果比第一个数小,就和他进行交换大于他就不进行交换)以此类推,每当你拿到新的牌,他之前的牌全是有序的,你只需考虑新牌应该排到哪里就好啦。
听懂我的故事了嘛,没听懂没关系哦~ 让我们一起看看源码吧
for(int i = 1 ; i < arr.length -1 ; i++){ //这就是你准备要排序的牌啦,我直接跳过了第一张的排序(又不傻)
for(int j = i - 1 ; j >= 0 && arr[j] > arr[j+1] ; j--){//这个j表示拍好数的最后一张牌哦
//当他比后一个数大的时候就需要进行交换啦
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
代码简单明了 其中第二个for循环有一丝丝难度(当然是对我)j表示已经排好序中最后一位
这是一个必要重要的排序相对于上几个档次要高为什么呢因为
时间复杂度 : O(N * log N) 空间复杂度 : O(N)
终于不是时间复杂度为O(N^2)的排序算法了,学会他功力大大提升!!,有没有学习他的冲动!
不用着急,让我们来盘一盘他是怎么实现排序的
整体上就是一个递归,左侧排好序之后让右侧排好序,最后让整体有序
感觉是不是不是很难,让我们看看代码:
public void guibing(int[] arr , int l , int r){
if(l = r){
return;
}
int mid = l + (r - l) >> 1;
guibing(arr, l , mid);
guibing(arr, mid + 1 , r);
merge(arr, l , mid , r);
}
private void merge(int[] arr , int l , int m , int r){
int[] help = new int[r - l +1];
int i = 0;
int p1 = l;
int p2 = m+1;
while(p1 <= m && p2 <=r){
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while(p1 <= m){
help[i++] = arr[p1++];
}
while(p2 <= r){
help[i++] = arr[p2++];
}
for(int j = 0 ; j < help.length ; j++){
arr[l+j] = help[j];
}
}
这是十分关键的一个排序哦,进大厂的小伙伴这个是必须要会的,和前面的排序相比,直接降维打击好吧!!
时间复杂度 : O(N * log N) 空间复杂度 : O(logN)
思想:先在数组中随机选一个数和最后一个进行交换,然后进行partition过程,然后左右进行递归
partition过程:将数组最后一个数为标准,使用双指针,小于他的放左边,等于他的放在中间,大于他的放在右边,然后将最后一位和大于他的区域第一个数进行交换,
是不是有点懵懵的,让我们看看源代码再说自己能不能看懂哈
public void kuaiPaiMain(int[] arr){
//对边界进行的划分
if(arr == null || arr.length <= 1){
return;
}
kuaipai(arr , 0 ,arr.length-1);
}
public void kuaiPai(int[] arr , int l , int r){
if(l >= r){
return;
}
//随机一个位置和最后位进行交换
int target = l+(int)(Math.random * (r - l +1))
int temp = arr[target];
arr[target] = arr[r];
arr[r] = temp;
//进行partition 然后左右分割继续递归
int[] p = partition(arr , l , r);
kuaipai(arr , l , p[0] - 1);//左
kuaipai(arr , p[1] + 1 , r);//右
}
public int[] partition(int[] arr , int l , int r){
int less = l-1;
int more = r;
//当l没有到达有边界more时,小于左边界扩移动l,大于右边界扩但不移动l,等于移动l
while(l < more){
if(arr[l] < arr[r]){
int temp = arr[l];
arr[l++] = arr[++less];
arr[less] = temp;
}if(arr[l] == arr[r]){
l++;
}else{
int temp = arr[--more];
arr[more] = arr[l];
arr[l] = temp;
}
}
}
int temp = arr[r];
arr[r] = arr[more];
arr[more] = temp;
//返回相等区域在左边界和右边界
return new int[] {less + 1 , more};
这是一个和快速排序一样地位的排序,将数组想象成一个完全二叉树利用二叉树的性质来完成排序。
时间复杂度 : O(N * log N) 空间复杂度 : O(1)
那么就有一个问题,怎么利用二叉树 :
利用这两点就可以完成排序啦!让我们来一起看看代码~
public void heapSort(int[] arr ){
if(arr == null || arr.length < 2){
return;
}
for(int i = arr.length - 1 ; i >= 0 ; i--){
heapify(arr , i , arr.length);
}
int size = arr.length;
swap(arr , 0 , --size);
while(size > 0){
heapify(arr , 0 , size);
swap(arr , 0 , --size);
}
}
public void heapify(int[] arr , int index , int size){
int left = index * 2 + 1;
while(left < size){
int lageNum = left +1 < size && arr[left + 1] > arr[left] ? left+1: left;
lageNum = lageNum > index ? lageNum : index;
if(lageNum == index){
break;
}
swap(arr , index , lageNum);
index = lageNum;
left = index * 2 + 1;
}
}
public void swap(int[] arr , int p , int q ){
int temp = arr[p] ;
arr[p] = arr[q];
arr[q] = temp;
}