排序
**排序:**就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作(默认为升序排序)。通常意义上的排序,都是指的原地排序(in place sort)。
算法分类:
-
按是否稳定,常见的十大排序可分为稳定的排序,和不稳定排序:
-
稳定性:原序列中,arr[i]=arr[j]的情况下,若元素arr[i]在arr[j]的前面,且在排序之后,arr[i]仍然在arr[j]的前面。既排序不改变相同元素的相对位置。
-
不稳定:与稳定性质相反,在排序之后,不能保证arr[i]仍然在arr[j]之前。既不保证相同元素的相对位置不变。
-
按是否比较,常见的十大排序可分为比较类排序,和非比较类排序:
-
比较类:通过相互比较决定元素之间的相对顺序。
-
非比较类:不需要通过元素之间相互比较,也能达到序列排序的目的
冒泡排序
冒泡排序:
在无序区间,通过相邻数的比较,将最大数冒泡的整个无序区间的最后,无序区间的最后边界向前缩小一个元素,反复冒泡,直至整体有序
(图片来源于排序答题管理)
代码实现
class Solution {
public int[] bubblingSort( int[] nums) {
for(int i=0;i<nums.length-1;i++){
boolean isSorted=true;//优化不必要的遍历检查
for(int j=0;j<nums.length-i-1;j++){
if(nums[j]>nums[j+1]){
int temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
isSorted=false;
}
}
if(isSorted){//如果本次没有交换,证明已经有序,直接退出
break;
}
}
return nums;
}
}
直接插入排序
插入排序,选择无序区间的第一个元素,在有序区间找位置插入,然后无序区间元素-1,有序+1,直到整体有序。
(图片来源于排序答题管理)
代码实现
class Solution {
public int[] sort( int[] nums) {
for(int i=1;i<nums.length;i++){
//有序区间[0,i)
//无序区间[i,nums.length)
int v=nums[i];//无序区间的第一个数
int j=i-1;
for(;j>=0&&nums[j]>v;j--){
nums[j+1]=nums[j];
}
nums[j+1]=v;
}
return nums;
}
}
归并排序
**归并排序:**归并排序采用的是分治法,先将每个子序列排序至有序,将已有的子序列合并成一个更大的子序列,重复操作,直至整个序列有序(先分再归)
(图片来源于排序答题管理)
代码实现
class Main {
public void mergeSort(int[] nums) {
mergeSortInternal(nums,0,nums.length);
}
private static void mergeSortInternal(int[]array,int low,int high){
if(low>=high-1){
return ;
}//分到每个数组块中只有一个元素
int mid=low+((right-left)>>1);
//[left,mid)左半部分
//[mid,right)右半部分
mergeSortInternal(array,low,mid);
mergeSortInternal(array,mid,high);
merge(array,low,mid,high);//归并
}
//[left,mid)[mid,right)
private static void merge(int[] array,int low,int mid,int high){
int i=low;
int j=mid;
int length=high-low;
int[]extra=new int[length];
int k=low;
//选择小的放入到extra
while(i<mid&&j<high){
if(array[i]<=array[j]){
extra[k++]=array[i++];
}else{
extra[k++]=array[j++];
}
}
//将剩下的元素放入到extra
while(i<mid){
extra[k++]=array[i++];
}
while(j<high){
extra[k++]=array[j++];
}
//从extra搬回到array
//System.arraycopy(extra,low,array,low,high-left),copyof底层调用arraycopy,并且申请空间,故使用arraycopy
for(int t=0;t<length;t++){
//搬回原位置,从low开始
array[low+t]=extra[t];
}
}
}
//循环
Class Main{
public void mergeSort(int[] nums) {
int[]temp=new int[nums.length];
int gap=1;
while(gap<nums.length){
for(int i=0;i<nums.length;i+=gap*2){
int left=i;
int mid=left+gap;
int right=mid+gap;
if(mid>nums.length){
mid=nums.length-1;
}
if(right>nums.length){
right=nums.length-1;
}
mergeDate(nums,left,mid,right,temp);
}
System.arraycopy(temp,0,nums,0,nums.length)
gap<<=1;
}
}
private static void mergeDate(int[]array,int left,int mid,int right,int[]temp){
int index=left;
int begin1=left;
int begin2=mid;
int k=0;
while(begin1<mid&&begin2<right){
if(array[begin1]<=array[begin2]){
temp[k++]=array[begin1++];
}else{
temp[k++]=array[begin2++];
}
}
while(begin1<mid){
temp[k++]=array[begin1++];
}
while(begin2<right){
temp[k++]=array[begin2++];
}
]
}