经典排序算法之冒泡、选择和插入排序

排序算法学了好久了,今天再来复习一下。毕竟是很经典的排序算法。

1 冒泡排序

算法描述

  设待排序记录序列中的记录个数为n
  一般地,第i趟起泡排序从1到n-i+1
  依次比较相邻两个记录的关键字,如果发生逆序,则交换之。
  其结果是这n-i+1个记录中,关键字最大的记录被交换到第n-i+1的位置上,最多作n-1趟。

算法实现:

package cn.hncu.sortAlgorithm;

public class SortMethods1 {
/*
 * 算法好坏的评价指标:
 * 1.时间复杂度,就是算法运行的快慢(时间)-----通常用计算机的运算(算术,赋值)次数来代替
 * 2.空间复杂度,占用内存空间的大小------通常用程序中使用了多少变量(栈内存,堆内存),这些变量总共占了多少内存
 */
	public static void main(String[] args) {
		int a[]={5,8,-3,11,7,28,95,-12,8};//8个数
		//1.冒泡排序
		//1.1普通的冒泡排序
		//bubbleSort(a);
		//1.2带优化的冒泡排序
		bubbleSort2(a);
	}
  //1.1普通的冒泡排序
	private static void bubbleSort(int[] a) {
		for(int i=0;i<a.length-1;i++){//趟数:n-1
			for(int j=0;j<a.length-i-1;j++){//让第j个和第j+1个数进行比较,违反需求则交换。j:0->j:n-i-1
				if(a[j]>a[j+1]){
					swap(a,j,j+1);
				}
			}
		}
	}

//1.2 冒泡排序(优化)----只要发现一趟走下来没有一次交换那么就认为已经排好序,后面的数就无需再遍历了
	private static void bubbleSort2(int[] a) {
		for(int i=0;i<a.length-1;i++){
			boolean isOk=true;
			for(int j=0;j<a.length-i-1;j++){
				if(a[j]>a[j+1]){
					swap(a,j,j+1);
					isOk=false;
				}
			}
			if(isOk) break;
		}
	}

算法评价


2 选择排序

算法描述

  首先通过n-1次比较,从n个数中找出最小的,将它与第一个数交换——第一趟选择排序,结果最小的数被安置在第一个元素位置上。
  再通过n-2次比较,从剩余的n-1个数中找出关键字次小的记录,将它与第二个数交换——第二趟选择排序。
  重复上述过程,共经过n-1趟排序后,排序结束。

算法实现:

//2.选择排序
		//2.1 选择排序的类似思维但性能不好----例如排手机
		//selectSort0(a);
		//2.2 真正的选择排序
		selectSort(a);
//2.1 选择排序的类似思维但性能不好
	private static void selectSort0(int[] a) {
		for(int i=0;i<a.length-1;i++){
			for(int j=i+1;j<a.length;j++){
				if(a[i]>a[j]){
					swap(a,i,j);
				}
			}
		}
	}
//2.2 选择排序
	private static void selectSort(int[] a) {
		for(int i=0;i<a.length-1;i++){
			int k=i;
			for(int j=i+1;j<a.length;j++){
				if(a[k]>a[j]) k=j; //要用a[k]和a[j]依次作比较,找出最小的那个
			}
			//经过上面的循环,第k个元素一定是当前(从第i个元素到最后这些元素中)最小的
			if(i!=k) swap(a,i,k);
		}
	}

算法评价


3 插入排序

算法描述:

  记录存放在数组R[0….n-1]中,排序过程的某一中间时刻,R被划分成两个子区间R[0…i-1]和R[i….n-1],其中:前一个子区间是已排好序的有序区;后一个子区间则是当前未排序的部分。

基本操作:

  将当前无序区的第1个记录R[i]插入到有序区R[0….i-1]中适当的位置,使R[0…i]变为新的有序区。

操作细节:

  当插入第i(i≥1)个对象时, 前面的r[0], r[1], …, r[i-1]已经排好序。

  用r[i]的关键字与r[i-1],r[i-2], …的关键字顺序进行比较(和顺序查找类似),如果小于,则将r[x]向后移动(插入位置后的记录向后顺移);找到插入位置即将r[i]插入。

算法实现:

//3. 插入排序
		//3.1 简单插入排序
		//insertSort(a);
// 3.1 简单插入排序
	private static void insertSort(int[] a) {
		//依次把每个元素拿来插入到有序序列当中(从第二个开始,到最后就行)
		for(int i=0;i<a.length-1;i++){
			//待插入的数
			int temp=a[i+1];
			
			//下面的这一段是决定temp所在的位置(j+1)以及 让比temp大的数往后挪动一个位置
			int j=i;
			//System.out.println(a[j]+".."+temp+".."+a[temp]);
			while(a[j]>temp){//如果有序数列中 第j位置的数 比待插入的数 大,则把a[j]往后挪动一个位置
				a[j+1]=a[j];// a[j] 挪到了a[j+1]的位置
				j--;
				if(j<0) break;
			}
			//这样找出来的第a[j]数是比temp小的数,所以让temp坐在第j个数的后一个位置:即j+1
			a[j+1]=temp;
		}
	}

3.2 二分插入排序(直接插入排序的优化)

算法描述:

  在直接插入排序的基础上,利用二分(折半)查找算法决策出当前元素所要插入的位置。

    二分查找:找到中间元素,如果中间元素比当前元素大,则当前元素要插入到中间元素的左侧;否则,中间元素比当前元素小,则当前元素要插入到中间元素的右侧。

  找到当前元素的插入位置i之后,把i和high之间的元素从后往前依次后移一个位置,然后再把当前元素放入位置i。

算法实现:

//3.2 加入二分查找的插入排序 //注:二分查找的前提要有序
		binaryInsertSort(a);
//3.2 加入二分查找的插入排序
	private static void binaryInsertSort(int[] a) {
		for(int i=0;i<a.length-1;i++){
			int temp=a[i+1];
			
			//用二分查找决定插入的位置
			int low=0;
			int high=i;
			while(low<=high){
				int mid=(low+high)/2;
				//用中间位置元素和当前待插入的数(temp)作比较
				if(a[mid]>temp)//落在左半区
					high=mid-1;
				else
					low=mid+1;
			}
			//上面这段只是找到插入位置
			
			//移位:把待插入位置腾出来
			for(int j=i;j>high;j--){
				a[j+1]=a[j];
			}
			//让temp坐在a[high+1]的位置上或者a[low]的位置上
			a[low]=temp;
		}
	}


亲测都是可以排序成功的哦。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值