九种基本排序算法

1 篇文章 0 订阅

排序分类:

1、插入排序:直接插入排序(InsertSort)、二分插入排序、希尔排序(ShellSort)

2、选择排序:简单选择排序、堆排序

3、交换排序:冒泡排序、快速排序

4、归并排序

5、基数排序

排序算法优劣指标:

 

(1)稳定性:当序列中存在两个或两个以上的关键字相等的时候,如果排序前序列中r1领先于r2,那么排序后r1如果仍旧领先r2的话,则是稳定的。(相等的元素排序后相对位置不变)

(2)不稳定性:当序列中存在两个或两个以上的关键字相等的时候,如果排序前序列中r1领先于r2,那么排序后r1如果落后r2的话,则是不稳定的。(相等的元素排序后相对位置发生改变)

(3)时间复杂度:算法的时间开销是衡量其好坏的最重要的标志。高效率的算法应该具有更少的比较次数和记录移动次数。

(4)空间复杂度:即执行算法所需要的辅助存储的空间。

 

 

 

直接插入排序:

基本思想:遍历序列的关键字,将待排序的关键字依次与其前一个关键字起逐个向前扫描比较,若是待排关键字小于扫描到的关键字,则将扫描到的关键字的向后移动一个位置,直到找到没有比待排关键字大的地方插入(待排序关键字前面的都是有序数列)

//直接插入排序
	public static void directInsertSort(int[] nums)
	{
		int i,j;
		int temp;
		for(i=1;i<nums.length;i++)//排序几趟 n-1
		{
			temp=nums[i];//待排数保存
			for(j=i-1;j>=0&&nums[j]>temp;j--)//每趟最多比较次数 i
			{
					nums[j+1]=nums[j];//如果扫描到的数大于待排数,则向后移一位
			}
				nums[j+1]=temp;
		}
	}

 

 

 

最坏情况:整个序列是逆序的时候,则内层循环的条件temp<nums[j]始终成立,此时对于每一次外层循环,内层循环次数每次达到最大值(即内层循环位i次),外层循环i取值为1~i-1,所以总的执行次数为n(n-1)/2 ,时间复杂度为O(n^2)。

最好情况:整个序列为正序的时候。内层循环条件始终不成立,所以内层循环始终不执行,始终执行语句nums[j+1]=temp。所以时间复杂度为O(n)。

空间复杂度:算法所需的辅助存储空间不随待排序列的规模变化而变化,是个常量,所以为O(1)。

二分插入排序:

二分插入排序算法实质上是对直接插入排序的一种优化,在排序数量大的情况下,速度远高于直接插入排序。

基本思想:以待排关键字所在位置将序列分为有序数列和无序数列两部分,然后对有序数列进行折半查找,找出一个点,左边的序列都是小于待排序关键字,该点与其右边至待排关键字的序列都是大于待排关键字的,将右边序列右移然后插入空处。

//二分插入排序
	public static void binaryInsertSort(int[] nums)
	{
		for(int i=1;i<nums.length;i++)//排序n-1趟 
		{
			//优化,减少不必要的查找,待排序关键字>待排序前一关键字,说明已经有序,反之则要排序
			if(nums[i]<nums[i-1])
			{
				int temp=nums[i];
				int left=0;
				int right=i-1;
				while(left<=right)
				{
					int mid=(left+right)/2;
                                        //left左边的都是比待排序关键字小的
					if(nums[mid]<temp)
					{
						left=mid+1;
					}else
					{
						right=mid-1;
					}
				}
				//将left起到待排关键字的右边的序列全部向右移动一位
				for(int j=i;j>left;j--)
				{
					nums[j]=nums[j-1];
				}
				nums[left]=temp;//插入有序数列
			}
		}
	}

最坏情况:整个序列是逆序的时候,则内层循环的条件left<=right.始终成立,此时对于每一次外层循环,第一个内循环达到最大值(log21~log2(n-1)),第二个内层循环次数每次达到最大值(即内层循环位i次),外层循环i取值为1~i-1,所以总的执行次数为n(n-1)/2 +nlog2n,时间复杂度为O(n^2)。

最好情况:整个序列为正序的时候。内层循环条件始终不成立,所以内层循环始终不执行,始终执行语句if(nums[i]<nums[i-1]),所以时间复杂度为O(n)。

空间复杂度:算法所需的辅助存储空间不随待排序列的规模变化而变化,是个常量,所以为O(1)。

冒泡排序:

基本思想:每次相邻两个关键字进行比较(0与1,1与2依次比较大小),小数上浮,大数下沉,每趟排序找出最大的数换到最右边。

//冒泡排序
	public static void bubbleSort(int[] nums){
		for(int i=0;i<nums.length-1;i++)
		{
			int flag=0;//flag用来标记本趟排序是否发生了交换
			for(int j=0;j<nums.length-1-i;j++)
			{
				
				int temp=nums[j];
				if(nums[j]>nums[j+1])
				{
					nums[j]=nums[j+1];
					nums[j+1]=temp;
					flag=1;//flag=1表示本次排序发生了交换
				}
			}
			System.out.print("冒泡第" + i + "趟排序:");
			printArray(nums);
			if(flag==0)//如果没有发生交换,说明序列有序,排序结束
			{
				return;
			}
		}
		
	}flag用来标记本趟排序是否发生了交换
			for(int j=0;j<nums.length-1-i;j++)
			{
				
				int temp=nums[j];
				if(nums[j]>nums[j+1])
				{
					nums[j]=nums[j+1];
					nums[j+1]=temp;
					flag=1;//flag=1表示本次排序发生了交换
				}
			}
			System.out.print("冒泡第" + i + "趟排序:");
			printArray(nums);
			if(flag==0)//如果没有发生交换,说明序列有序,排序结束
			{
				return;
			}
		}
		
	}

最坏情况:序列逆序,此时内层循环if语句的条件始终成立,基本操作执行的次数为n-i。i取值为1~n-1,所以总的执行次数为(n-1+1)(n-1)/2=n(n-1)/2,所以时间复杂度为O(n^2)。

最好情况:序列正序。此时内层循环的条件比较语句始终不成立,不发生交换,内层循环执行n-1次,所以时间复杂度为O(n)。

空间复杂度为O(1)。

简单选择排序:

基本思想:第i次遍历序列,找到最小的数,与第i个数交换。

//简单选择排序
	public static void selectSort(int[] nums)
	{
		
		for(int i=0;i<nums.length-1;i++)
		{
			int j=0;
			int temp;
			int k=i;//保存每趟找到的最小数
			for(j=i+1;j<nums.length;j++)
			{
				if(nums[k]>nums[j])
				{
					k=j;
				}
			}
			if(k!=i)//如果找到了最小数,并且不是当前待排数关键字,交换
			{
				temp=nums[i];
				nums[i]=nums[k];
				nums[k]=temp;
			}
			System.out.print("选择第" + i + "趟排序:");
			printArray(nums);
		}
	}

时间复杂度:O(n^2)

空间复杂度:O(1)

快速排序:

基本思想:

第一步:i=0,选出一个基准数key=nums[i](可以是第一个,也可以是中间的,都无所谓)保存,第二步:(j=nums.length-1)从右至左遍历序列直到遍历到的这个数小于该基准数,将该数放到基准数的位置(nums[i]=nums[j];(i++)),第三步:从左至右遍历序列直到遍历到的数大于该基准,将该数移动到之前第二步替换基准数的那个数的位置nums[j]=nums[i] ;j++。然后重复2,3步,直到i=j,将基准数放到i这个位置

public void quickSort(int[] a,int low,int high){
    if(low>high)
        return;
    int i,j,key;
    i=low;
    j=high;
    key=a[low];
    while(i<j){
        while(i<j&&a[j]>key){
            j--;
        }
        if(i<j){
            a[i++]=a[j];
        }
        while(i<j&&a[i]<key){
            i++;
        }
        if(i<j){
            a[j--]=a[i];
        }
    }
    a[i]=key;
    quickSort(a,low,i-1);
    quickSort(a,i+1,high);
}

还没写完 持续更新中……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值