排序1——稳定的排序

排序图
排序

排序

**排序:**就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作(默认为升序排序)。通常意义上的排序,都是指的原地排序(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++];
	    }
    ]
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值