简单排序——选择排序、冒泡排序、插入排序

1. 选择排序

1.1 选择排序算法原理

        以序列首元素位置为基准位置,每次将该基准位置的元素和后面元素逐个进行比较,挑选最大或者最小的那个数放在基准位置上,一趟比较结束后,然后将基准位置设置为该位置的下一位置,重复上述操作,直到基准被安排在序列的最后一个位置时,此时序列已经排列完成。

1.2 选择排序过程分析

例如:48,12,61,3,5,19,32,7,24,31

说明:按照从小到大的顺序进行排序,其中每条彩色线条为两数之间的比较,其条数为比较次数。

①第一趟比较:

        当基准所在位置下标0进行完第一次循环比较后,可以看到此时min在下标为3的位置,所以要将下标为0的元素和下标为3的元素进行交换,也就是48和3交换,此时待排数组变成3,12,61,48,5,19,32,7,24,31,第一趟选择排序比较结束。

②第二趟比较:

        此时基准在下标为1的位置,初始化min=1,对应的元素为12,12分别与后面的元素作比较,当比较到下标为4时,对应的元素为5,12>5,所以min=4,然后5再跟后面的元素作比较,一直比较到最后一个元素,都没有比5小的元素,所以基准所在位置1的对应元素要和min所在位置4的对应元素交换,也就是12和5交换,然后待排数组变成3,5,61,48,12,19,32,7,24,31,第二趟选择排序比较结束。

③第三趟比较:

        此时基准在下标为2的位置,初始化min=2,对应的元素为61,61分别与后面的元素作比较,当比较到下标为3时,对应的元素为48,61>48,所以min=3。然后48再和后面的元素进行比较,当比较到下标为4时,对应的元素为12,48>12,所以min=4。然后12再跟后面的元素进行比较,当比较到下标为7时,对应的元素为7,12>7,所以min=7。然后7再跟后面的元素进行比较,一直比较到最后一个元素,都没有比7小的元素,所以基准所在位置2的对应元素要和min所在位置7的对应元素交换,也就是61和7交换,然后待排数组变成3,5,7,48,12,19,32,61,24,31,第三趟选择排序比较结束。

        以此类推,一直比较到基准在下标为8的位置,执行好比较之后待排数组就是排序好的数组了,得到排序数组为3,5,7,12,19,24,31,32,48,61。

1.3 选择排序核心代码及说明

/*选择排序算法*/

/*比如待排数组为1 5 2*/

/*第一趟排序如下*/

/*此时min=1,首先第一次循环就以第一个元素1为标志,1分别与数组中其他元素比较*/

/*如果有元素比1小,那么就把那个元素的下标存到min中*/

/*一直比较到数组最后一个元素,然后把min下标对应的元素与第一个元素交换*/

/*因为待排序列中第一个元素1与其他元素比较,都没有比他小的值,所以不需要交换,1就是排序的第一个元素*/

/*第二趟排序如下*/

/*此时min=2,因为排序序列的第一个元素我们在第一趟中已经找到了最小值去填充这个位置,所以第二趟排序我们需要找第二个元素*/

/*第二个元素为5,要和后面的数组元素进行比较,跟第一趟排序一样,如果后面的元素大于2,那么min就等于那个元素所对应的下标*/

/*一直比较到最后一个元素,然后将min下标对应的元素与第二个元素交换*/

/*待排数组中5>2,所以2要跟5交换位置,此时数组变成1 2 5*/

/*因为待排数组的长度为3,只需要进行3-1=2次排序,所以不需要进行第三趟排序了,此时就是给定待排数组1 5 2的排序好的数组1 2 5了*/

/*对于其他待排长度为len的数组,我们需要进行len-1趟排序*/

/*因为我们有两层循环,一层循环是用来标志排序数组当前要找到的位置的元素的下标,一层循环用来比较大小,所以时间复杂度为O(N²)*/

/*由于使用了中间变量b,所以空间复杂度为O(1)*/



import java.util.Arrays;
public class selectionSort {
	
	//方法1
	public static void SelectionSort(int[] arr) {
		if(arr==null || arr.length <2) {     //假设数组为空或者数组中只有一个数,直接返回
			return;
		}
		// 0 ~ N-1  找到最小值,在哪,放到0位置上
		// 1 ~ n-1  找到最小值,在哪,放到1 位置上
		// 2 ~ n-1  找到最小值,在哪,放到2 位置上
		for(int i=0;i<arr.length-1;i++) {   //从下标为0的位置开始
			int minIndex=i;
			for(int j=i+1;j<arr.length;j++) {   //与数组中其他的数依次对比
				minIndex =arr[j]<arr[minIndex] ? j:minIndex;
			}
			swap(arr,i,minIndex);
		}
	}
	
	public static void swap(int[] arr,int i,int j) {  
		//交换函数
		int b;
		b= arr[i];
		arr[i]=arr[j];
		arr[j]=b;
	}
	
	
	
	public static void main(String[] args) {
		int[] arr= {1,6,8,2};
		System.out.println(Arrays.toString(arr));//打印排序前的数组
		SelectionSort(arr);
		System.out.print(Arrays.toString(arr)); //打印排序后的数组
		
	}
}


2. 冒泡排序

2.1 冒泡排序算法原理

        比较相邻的元素,将大的元素交换到右边的位置,重复多次后,最大元素就“冒泡”到列表的最后一个位置。第二遍将第二大元素沉下去,N-1遍后结束。

2.2 冒泡排序过程分析

例如:48,12,61,3,5

说明:按照从小到大的顺序进行排序,其中每条彩色线条为两数之间的比较,其条数为比较次数。

①第一趟比较:

        当基准所在位置下标0进行完第一次循环比较后,可以看到此时max在一次次的交换中来到了数组中的最后一个位置,下标为4,也就是N-1(N为待排数组的元素个数)。此时待排数组变成[12 48 3 5 61],第一趟冒泡排序比较结束。

②第二趟比较:

        此时基准在下标为0的位置,初始化max=12,12与后面的元素作比较,12<48,所以此时max=48,不交换位置;接着max继续与下一个数比较,48>3,交换48和3;接着48继续与下一个数比较,48>5,交换48和5的位置,此时48已经来到了倒数第二个位置,因为最后一个数已经在第一次比较中确定位置,因此48不需要再跟它比较。此时待排数组变成[12 3 5 48 61],第二趟选择排序比较结束。

③第三趟比较:

        此时基准在下标为0的位置,初始化max=12,12与后面的元素作比较,12>3,所以交换12和3接着max继续与下一个数比较,12>5,交换12和5,此时12已经来到了倒数第3个位置,后面的数已经排序完成,因此12不需要再跟它们比较。此时待排数组变成[3 5 12 48 61],第三趟选择排序比较结束。

④第四趟比较:

        此时基准在下标为0的位置,初始化max=3,3与后面的元素作比较,5>3,此时max=5,不交换位置。此时5已经来到了倒数第4个位置,后面的数已经排序完成,因此5不需要再跟它们比较。此时待排数组变成[3 5 12 48 61],第四趟选择排序比较结束,此时进行了4次比较,也就是N-1次,因此冒泡排序结束,得到排序数组为[3 5 12 48 61]。

2.3 冒泡排序核心代码

import java.util.Arrays;
public class bubbleSort {
	public static void BubbleSort(int[] arr) {
		if(arr ==null || arr.length<2) {
			return;
		}
		// 0 ~ N-1
		// 0 ~ N-2
		// 0 ~ N-3
		for(int i = arr.length - 1 ; i > 0 ; i-- ) {  
			for(int j=0 ; j<i ; j++) {
				if(arr[j] > arr[j+1]) {
					swap(arr,j,j+1);
				}
			}
		}
	}
	public static void swap(int[] arr,int i,int j) {
		int b;
		b=arr[i];
		arr[i]=arr[j];
		arr[j]=b;
	}
	public static void main(String[] args) {
		int[] arr= {1,8,6,7,2,3};
		System.out.println(Arrays.toString(arr));
		BubbleSort(arr);
		System.out.print(Arrays.toString(arr));
	}

}

3. 插入排序

3.1 插入排序算法步骤

        将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

        从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

3.2 插入排序算法步骤

①第一趟比较:

        此时待插入元素的下标为i=1,对应的元素为12,令b=12,接着12跟前面的元素进行比较,也就是下标j=i-1=0对应的元素48,因为48>12,所以需要把48向后面挪一个位置,也就是48要移动到j+1=1下标的地方。因为此时j=0,所以循环结束,将b=12插入到j+1=0的位置(因为循环解释的条件为j<=0或b<a[j],然后j--,所以此时j=-1,j+1=0),第一趟插入排序比较结束。此时待排数组为[12,48,61,3,5,19,32,7,24,31]。

②第二趟比较:

        此时待插入元素的下标为i=2,对应的元素为61,令b=61,接着61跟前面的元素进行比较,也就是下标j=i-1=1对应的元素48,因为61>48,所以循环结束,第二趟插入排序比较结束。

此时待排数组为[12,48,61,3,5,19,32,7,24,31]。

③第三趟比较:

        此时待插入元素的下标为i=3,对应的元素为3,令b=3,接着3跟前面的元素进行比较,也就是下标j=i-1=2对应的元素61,因为61>3,所以需要把61向后面挪一个位置,也就是61要移动到j+1=3下标的地方。然后3继续跟前面的元素进行比较,也就是下标j=j-1=1对应的元素48,因为48>3,所以需要把48向后面挪一个位置,也就是48要移动到j+1=2下标的地方。然后3继续跟前面的元素进行比较,也就是下标j=j-1=0对应的元素12,因为12>3,所以需要把12向后面挪一个位置,也就是12要移动到j+1=1下标的地方。因为此时已经比较到了数组的第一个元素,前面没有元素了,所以循环结束,将b=3插入到j+1=0的位置(因为循环解释的条件为j<=0或b<a[j],然后j--,所以此时j=-1,j+1=0),第三趟插入排序比较结束。

        此时待排数组为[3,12,48,61,5,19,32,7,24,31]

3.3 插入排序核心代码及说明

import java.util.Arrays;

public class InsertionSort {
	public static void insertSort(int[] arr) {
		if(arr==null || arr.length<2) {
			return;
		}
		// 0 ~ i 做到有序
		for(int i=0;i<arr.length;i++) {
			for(int j = i-1 ; j >= 0 ;j--) {
				if(arr[j]>arr[j+1]) {
					swap(arr,j,j+1);
				}
			}
			
		}
	}
	public static void swap(int[] arr,int i,int j) {
		int b;
		b= arr[i];
		arr[i]=arr[j];
		arr[j]=b;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr = {1,5,7,3,4,2,9};
		System.out.println(Arrays.toString(arr));
		insertSort(arr);
		System.out.println(Arrays.toString(arr));
	}

}


3.4 二分法改进插入排序

        折半插入排序算法的时间复杂度:O(nlogn)

        折半插入排序利用二分法的思想,在一个有序的序列中,找到新元素在该序列中的位置,然后插入。如图1所示,共有n个元素,前i个元素已经是有序序列,现在要将第i个元素插入其中。折半插入排序需要做两步工作:找到待插入元素的位置、插入。

        首先要定义两个指针(不是语法里面的指针,是下标的意思) low 和 high 用于寻找 a[i] 的插入位置,low 指向a[0],high 指向 a[i-1] 中点 mid=(low+high)/2,

        如图2所示二分法的思想是,比较a[i]与a[mid]的大小,若 a[i]>a[mid] ,说明a[i]的位置应该在 mid-high 之间,将区间 [low,high] 缩短为 [mid+1,high] ,令指针 low=mid+1 ;若 a[i]<=a[mid] ,说明a[i]的位置应该在 low-mid 之间,将区间压缩为[low,mid-1],令指针high=mid-1。每次折半之后,a[i]的位置应该在 [low,high] 之间

        如此循环,low与high渐渐靠近,直到 low>high 跳出循环,a[i]的位置找到,low即为a[i]应该放置的位置。

        找到a[i]的位置之后进行插入,先将 a[low]~a[i-1] 这些元素向后平移一个元素的位置,然后将a[i]放到low位置。

代码如下:

void BinSort(int *a,int n)
{
        int i,j;
        for(i=1;i<n;i++) /*开始 以a[0]作为有序序列,从a[1]开始找到当前元素a[i]应该放置的位置 */
        {
                int low=0,high = i-1,mid;/*每次寻找a[i]的位置,都要更新这些数据 */
 
                while(low<=high) /*二分思想循环寻找a[i]的位置 */
                {
                        mid = (low+high) / 2;  
                        if(a[i]<=a[mid])
                                high = mid - 1;  /*high指针减小 */
                        else
                                low = mid + 1;   /*low指针增加 */
                }  /*循环结束,low就是a[i]应该放置的位置 */
                
                int temp = a[i];  
                for(j=i;j>low;j--)  /*将元素向后平移*/
                        a[j] = a[j-1];  
                a[low] = temp;   /*将元素temp = a[i] 放置到low位置 */
        }
}

其他相关文章参考:

算法复杂度:快速搞懂算法复杂度 - 掘金 (juejin.cn)

二分法求解问题:对半切快速解题——二分法 - 掘金 (juejin.cn)

作者:ee在努力
链接:https://juejin.cn/post/7236634496766722108
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Python 中,你可以使用内置的 `sorted` 函数来对列表进行排序。例如: ```python numbers = [3, 4, 2, 1] sorted_numbers = sorted(numbers) print(sorted_numbers) # 输出: [1, 2, 3, 4] ``` 你也可以使用列表的 `sort` 方法来对列表进行排序。与 `sorted` 函数不同的是,`sort` 方法是在原地对列表进行排序,也就是说不会返回一个新的列表,而是直接修改原来的列表。例如: ```python numbers = [3, 4, 2, 1] numbers.sort() print(numbers) # 输出: [1, 2, 3, 4] ``` 你也可以使用 Python 的 heapq 库中的堆排序算法。堆排序是一种速度较快的排序算法,特别适用于海量数据的排序。例如: ```python import heapq numbers = [3, 4, 2, 1] heapq.heapify(numbers) # 将列表转化为堆 sorted_numbers = [] while numbers: sorted_numbers.append(heapq.heappop(numbers)) # 将堆中最小的数取出并放到结果列表中 print(sorted_numbers) # 输出: [1, 2, 3, 4] ``` 此外,Python 还提供了许多其他的排序算法,例如快速排序、归并排序等。你可以使用 Python 的 timeit 库来对不同的排序算法进行测试,以找出最快的排序算法。 ### 回答2: 数据结构是计算机科学中非常重要的一个概念,它是一种组织和存储数据的方式。而实现排序算法数据结构中的一个重要应用。 在Python中,可以使用多种数据结构来实现排序算法,比如列表、数组和堆等。下面我将介绍一种常用的排序算法——插入排序的Python实现。 插入排序是一种简单且常用的排序算法,它的基本思想是将待排序的元素一个一个地按照大小插入到已经排好序的列表中。具体步骤如下: 1. 创建一个新的空列表,作为存放已排序元素的容器。 2. 遍历待排序的列表,依次取出每个元素。 3. 将取出的元素与已排序元素的最后一个元素比较,如果取出的元素较小,则将它插入到已排序元素的末尾;如果取出的元素较大,则向前比较,找到合适的位置插入。 4. 重复步骤3,直到待排序列表中的所有元素都被取出并插入到已排序列表中。 5. 返回已排序的列表,即为排序结果。 下面是插入排序的Python实现代码: ```python def insertion_sort(arr): for i in range(1, len(arr)): key = arr[i] j = i - 1 while j >= 0 and arr[j] > key: arr[j + 1] = arr[j] j -= 1 arr[j + 1] = key return arr ``` 通过调用`insertion_sort`函数,传入待排序的列表,即可得到排序结果。 这就是数据结构中一种常用排序算法——插入排序的Python实现。当然,除了插入排序,还有许多其他排序算法也可以使用Python来实现,比如冒泡排序、快速排序等。每种排序算法都有其特点和适用场景,可以根据具体需求选择合适的排序算法来使用。 ### 回答3: 数据结构是计算机存储、组织和管理数据的方式。在Python中,可以使用不同的数据结构来实现排序算法。 常见的排序算法冒泡排序插入排序选择排序、快速排序、堆排序和归并排序等。 冒泡排序是一种比较简单排序算法,它重复地交换相邻的元素,直到整个序列有序为止。可以使用列表作为数据结构来实现冒泡排序插入排序是一种较为直观的排序算法,它将未排序的元素逐个插入到已排序的部分中,构建有序序列。也可以使用列表实现插入排序选择排序是一种简单直观的排序算法,它每次选择未排序部分的最小元素,并将其与未排序部分的最左边元素交换位置。同样可以使用列表来实现选择排序。 快速排序是一种常用的排序算法,它使用分治的思想,将序列分为两个子序列,递归地排序子序列。同样可以使用列表作为数据结构来实现快速排序。 堆排序是一种利用堆的数据结构来进行排序算法,它通过不断地构建和调整堆来达到排序的目的。可以使用列表来实现堆排序。 归并排序是一种稳定的排序算法,它使用分治的思想,将序列分为两个子序列,递归地排序子序列,然后将两个有序子序列合并为一个有序序列。同样可以使用列表来实现归并排序。 总的来说,Python提供了多种数据结构算法来实现排序操作,根据实际需求和性能要求选择适合的算法数据结构

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值