基础排序算法(1)-冒泡排序/插入排序/选择排序/归并排序/快速排序

几种基础排序算法及其比较

以下为个人学习总结 。如有不妥,热泪希望指正

1 冒泡排序

  • 思路(从小到大):
    (1)假设数据长度为N。总共要排序N-1轮。
    (2)在每一轮排序中。相邻两个元素之间进行比较。不符合排序顺序的两个进行位置交换。每一轮结束后。教大的元素都被移到了最右侧。

  • 冒泡思路示意图

  • 代码示意

		boolean isSorted= false;//是否已经完全排序好的标记
		for(int i=0;i<nums.length-1;i++) {//这层循环控制总共要排序几轮
			isSorted= true;//flag标记用于检查每一轮是否有元素进行交换。
						//如果没有。说明都是排序好的。可以提前退出循环
			for(int j=0;j<nums.length-1-i;j++) {//注意j的循环结束条件。因为从右往前的i个元素都是已经排序好的
				if(nums[j]>nums[j+1]) {
					int temp = nums[j];
					nums[j] = nums[j+1];
					nums[j+1] = temp;
					isSorted= false;
				}
			}
			if(isSorted) break;
		}
  • 复杂度分析
时间复杂度空间复杂度是否是稳定排序
O(n^2)O(1)
  • 冒泡排序的优化1 --减少总轮数和每轮的比较数
  • 优化点1 :假设一个待排数组为【5,1,2,3,4】
    如果是这种情况,那么在第一轮排序后,整个数组已经达到正确的顺序。
    按原来的写法仍然是会比较接下来的3轮。
  • 优化点2 :假设一个待排数组为【4,3,1,7,8,9,10】
    如果是这种情况,在第一轮排序后,数组的元素排序情况是[3,1,4,7,8,9,10]。那么在第二轮排序的时候,元素1后面的数字们都已经按正确的位置排好了,是不需要一直比较到元素9的位置。而按原来的写法是会一致比较到底的

所以基于以上两个问题。优化冒泡排序

  • 代码示意
public static void bubbleSort(int[] nums) {
		boolean isSorted = true; //isSorted:优化点1:如果已经是排序好的,不需要再实行接下来的几轮
		int goodSortedIndex = nums.length-1; //goodSortedIndex:优化点2:如果在其中某一轮的比较过程中,已经是排序好的,则不需要一直比较到最后。
		for(int i=0;i<nums.length-1 ;i++) {//这层循环控制总共要排序几轮
			isSorted = true;
			int m = 0;
			for(int j=0;j<goodSortedIndex;j++) {//注意j的循环结束条件。因为从右往前的i个元素都是已经排序好的
				if(nums[j]>nums[j+1]) {
					int temp = nums[j];
					nums[j] = nums[j+1];
					nums[j+1] = temp;
					isSorted = false;
					m =j;//记录当前比较的位置
				}
			}
			goodSortedIndex = m;
			if(isSorted) break;
		}
	}	

2 插入排序

  • 思路:
    将数组可以看成两部分。一部分是有序的。一部分是无序的。
    从无序中拿数字,在有序部分中找到合适位置插入。
    在这里插入图片描述
  • 复杂度分析
时间复杂度空间复杂度是否是稳定排序
O(n^2)O(1)
  • 代码如下
public void insertSort(int[] nums) {
		for(int i =1;i<nums.length;i++) {
			int value = nums[i];
			int j =i;
			for(;j>1;j--) {
				if(value <nums[j-1]) { //如果左边的元素比value大,左边元素往右移。
					nums[j] = nums[j-1];
				}else {     //如果左边的元素较小,不需要再比较了,直接调出本轮循环
					break;
				}
			}
			nums[j] = value;//将value插入正确的位置

		}

	}

3 选择排序

  • 思路:
    将数组分为两部分,一部分为已排区,一部分为待排区。
    每次从待排区找到最小的值。交换到已排区

在这里插入图片描述

  • 复杂度分析
时间复杂度空间复杂度是否是稳定排序
O(n^2)O(1)(因为交换位置会使相对位置发生变化)
  • 代码如下
public void chooseSort(int[] nums) {
		
		for(int i = 0;i<nums.length-1;i++) {
			int minIndex = i;
			for(int j = i+1;j<nums.length;j++) {
				if(nums[j] <nums[minIndex]) {
					minIndex = j;
				}
			}
			//一轮比较完后,将最小的元素移动到有序区的最后面
			int temp  = nums[i];
			nums[i] =nums[minIndex];
			nums[minIndex] = temp;
			
		}
		
		
	}

4 归并排序

  • 思路:将数据递归一分为二,直到不能再分解时,两个小数组进行有序合并。分而治之
  • 图示
    在这里插入图片描述
/**
	 * 归并排序
	 * @param nums
	 * @param start
	 * @param end
	 */
	public void mergeSort(int[] nums,int start,int end) {
		if(start == end) {//数据不能再分的出口
			return;
		}
		
		//将待排序数据一分为二、
		int mid = start+(end-start)/2;//分界的中点		
		mergeSort(nums,start,mid);
		mergeSort(nums,mid+1,end);//注意这里mid+1
		
		//然后合并
		merge(nums,start,mid,end);
		
	}
	/**
	 * 归并排序之合并
	 * @param nums
	 * @param start
	 * @param end
	 */
	private void merge(int[] nums, int start, int mid,int end) {
		System.out.println("归并排序开始");
		int[] temp = new int[end-start+1];//申请一个临时数组
		int t =0;
		//i指针前一半待排序的数组位置,j指针代表后一半待排序的数组的位置
		int i = start;
		int j = mid+1;
		for(;i<=mid && j <=end;) {
			if(nums[i] <=nums[j]) {
				temp[t]=nums[i++];
			}else {
				temp[t] = nums[j++];
			}
			t++;
		}
		//判断哪半组数据还剩余
		int rest =0;
		if(j != end+1) {
			rest = j;
		}else {
			rest = i;
		}
		//将属于的数据加入到temp中
		while(t<=end-start) {
			temp[t++] = nums[rest++];
		}
		
		//将temp数据的数组赋值到nums中
		t--;
		while(t>=0) {
			nums[end--]  =temp[t--];
		}
	}
	
	
  • 复杂度分析
时间复杂度空间复杂度是否是稳定排序
O(nlogn)O(n)**是

5 快速排序

  • 思路:定义一个基准点pivot。然后根据基准点将数据分成两半。
  • 图解:
    在这里插入图片描述
  • 代码如下
/**
	 * 快速排序
	 * @param nums
	 * @param start
	 * @param end
	 */
	public void quickSort(int[] nums,int start,int end) {
		if(start >= end) {
			return;
		}
		int partition = partition(nums,start,end);//分区,返回最后的分区节点
		quickSort(nums,partition+1,end);
		quickSort(nums,start,partition-1);
	}

	private int partition(int[] nums,int start, int end) {
		int left = start;
		int right = end;
		int pivot = nums[start];
		while(left < right) {				
			//右指针往左移,直到找到数字比pivot小时,停下
			//这种解法下,必须右指针先动。
			while(left<right && nums[right] >pivot) {
				right--;
			}
			//左指针往右移,直到找到数字比pivot大时,停下
			while(left<right && nums[left]<=pivot) {
				left++;
			}
			
			//交换左右两个指针指向的值
			if(left<right) {
				int tmp = nums[left];
				nums[left] = nums[right];
				nums[right]  = tmp;
				
			}
		}
		//将pivot指针的值和左指针的值交换
		nums[start] = nums[left];
		nums[left] = pivot;
		
		return left;
	}
  • 复杂度分析
时间复杂度空间复杂度是否是稳定排序
O(nlogn)O(1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值