03、选择排序,插入排序算法图解及代码(java)

1、选择排序

         选择排序(Selection sort)是一种简单直观的排序算法。其基本思想是:首先在未排序的数列中找到最小(or最大)元素,然后将其存放到数列的起始位置;接着,再从剩余未排序的元素中继续寻找最小(or最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。


        样例:以数列{20,40,30,10,60,50}为例,演示其选择排序过程(如下图)。

排序流程如下:

第1趟:i=0。找出a[1]至a[5]中的最小值a[3]=10,然后将a[0]和a[3]互换。 数组变化:20,40,30,10,60,50 -- > 10,40,30,20,60,50

第2趟:i=1。找出a[2]至a[5]中的最小值a[3]=20,然后将a[1]和a[3]互换。 数组变化:10,40,30,20,60,50 -- > 10,20,30,40,60,50

第3趟:i=2。找出a[3]至a[5]中的最小值,由于该最小值大于a[2],该趟不做任何处理。

第4趟:i=3。找出a[4]至a[5]中的最小值,由于该最小值大于a[3],该趟不做任何处理。

第5趟:i=4。交换a[4]和a[5]的数据。 数组变化:10,20,30,40,60,50 -- > 10,20,30,40,50,60

程序:

package basic_package_01;

import java.util.Arrays;

//选择排序
public class Code_01_SelectionSort {
	
	public static void selectionSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;     //排序的元素不为空且必须大于等于2个元素。
		}
		for(int i = 0; i < arr.length-1; i++) {
			int minIndex = i;
			// 寻找a[i+1]至序列末尾的最小值
			for (int j = i + 1; j < arr.length; j++) {
				minIndex = arr[j] < arr[minIndex] ? j : minIndex;
			}
			swap(arr, i, minIndex);
			System.out.print("第"+ (i+1) +"躺:"+"找到的最小值下标是"+minIndex+", 本次排序结果为:");
			printArray(arr);
		}
	}
	
	private static void swap(int[] arr, int i, int j) {
		// TODO Auto-generated method stub
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}
	
	// 打印数组
	public static void printArray(int[] arr) {
		if (arr == null) {
			return;
		}
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}
	
	public static void main(String[] args) {
		int[] arr = {20,40,30,10,60,50};
		System.out.print("待排序序列:");	
		printArray(arr);	//打印原始数组
		selectionSort(arr);
		System.out.print("最终序列:");	
		printArray(arr);
	}
	
}

程序结果:

时间复杂度和稳定性

        选择排序的时间复杂度是 O(N²) :假设被排序的数列中有N个数。遍历一趟的时间复杂度是O(N),需要遍历多少次呢?N-1次,因此,选择排序的时间复杂度是 O(N²) 。

        选择排序是稳定的算法,它满足稳定算法的定义:假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!

        注:引用文章来源通俗易懂讲解 选择排序 - 知乎 


2、 插入排序

插入法排序原理
        利用插入法对无序数组排序时,我们其实是将数组R划分成两个子区间R[1..i-1](已排好序的有序区)和R[i..n](当前未排序的部分,可称无序区)。插入排序的基本操作是将当前无序区的第1个记录R[i]插人到有序区R[1..i-1]中适当的位置上,使R[1..i]变为新的有序区。因为这种方法每次使有序区增加1个记录,通常称增量法。
        插入排序与打扑克时整理手上的牌非常类似。摸来的第1张牌无须整理,此后每次从桌上的牌(无序区)中摸最上面的1张并插入左手的牌(有序区)中正确的位置上。为了找到这个正确的位置,须自左向右(或自右向左)将摸来的牌与左手中已有的牌逐一比较。

插入排序法动态图

        图解:根据其原理,我们把该无序数列看成两个部分,我们不难看出图中,首先我们把第一位3看成是有序数列,剩下的作为无序数列,因为要把后面的无序数列中的数插入到前面有序数列,所以依次把后面的数抽出,在前面找到合适位置插入。如图,先抽出44,与前面比较,比3大放在3后面,再抽出38,与前面比较,比44小,比3大,所以插入到3后面。依次类推,直到最后的一个数也插入到前面的有序数列中。

        例:数组{9,3,1,4,2,7,8,6,5}。

在这里插入图片描述

————————————————
版权声明:本文为CSDN博主「萌中芢」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42857603/article/details/81605124 

   代码:

package basic_package_01;

public class Code_01_InsertionSort {
	public static void insertionSort(int[] arr) {
		if(arr == null || arr.length < 2) {
			return;
		}
		for (int i = 1; i < arr.length; i++) {
			for(int j = i-1; j >= 0 && arr[j] > arr[j+1]; j--) {
				swap(arr, j , j+1);
			}
			System.out.print("第" + i +"次,调换后排序结果:");
			printArray(arr);
		}
	}
	
	private static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}
	
	// 打印数组
	public static void printArray(int[] arr) {
		if (arr == null) {
			return;
		}
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}
		
	public static void main(String[] args) {
		int[] arr = {9,3,1,4,2,7,8,6,5};
		System.out.print("待排序序列:");	
		printArray(arr);	//打印原始数组
		insertionSort(arr);
		System.out.print("最终序列:");	
		printArray(arr);
		}
}

输出结果:

时间复杂度

        在插入排序中,当待排序数组是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较N- 1次,时间复杂度为O(N)。

        最坏的情况是待排序数组是逆序的,此时需要比较次数最多,总次数记为:1+2+3+…+N-1,所以,插入排序最坏情况下的时间复杂度为O(N²) 。

        平均来说,A[1..j-1]中的一半元素小于A[j],一半元素大于A[j]。插入排序在平均情况运行时间与最坏情况运行时间一样,是输入规模的二次函数。

空间复杂度

        插入排序的空间复杂度为常数阶O(1)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值