2023 跟我一起学算法:选择排序

排序算法

什么是排序?

排序算法用于根据元素上的比较运算符重新排列给定的数组或元素列表。比较运算符用于决定相应数据结构中元素的新顺序。

例如:下面的字符列表按其 ASCII 值的升序排序。也就是说,具有较小 ASCII 值的字符将比具有较高 ASCII 值的字符先放置。

选择排序

选择排序是一种简单而高效的排序算法,其工作原理是重复从列表的未排序部分中选择最小(或最大)元素并将其移动到列表的已排序部分。

"选择排序"算法工作原理

让我们以以下数组为例:arr[] = {64, 25, 12, 22, 11}

第一遍:

  • 对于排序数组中的第一个位置,从索引 0 到 4 顺序遍历整个数组。当前存储64 的第一个位置,遍历整个数组后很明显11是最低值。
  • 因此,将 64 替换为 11。一次迭代后, 11(恰好是数组中的最小值)往往会出现在排序列表的第一个位置。

第二遍:

  • 对于存在 25 的第二个位置,再次按顺序遍历数组的其余部分。
  • 遍历完后,我们发现12是数组中倒数第二小的值,它应该出现在数组的第二位,因此交换这些值。

第三遍:

  • 现在,对于第三个位置,其中存在**25,**再次遍历数组的其余部分并找到数组中存在的第三个最小值。
  • 遍历时,22 是第三个最小值,它应该出现在数组中的第三个位置,因此将22与第三个位置上的元素交换。

第四遍:

  • 类似地,对于第四个位置,遍历数组的其余部分并找到数组中第四小的元素
  • 由于25是第四低的值,因此它将排在第四位。

第五遍:

  • 最后,数组中存在的最大值自动放置在数组的最后一个位置
  • 结果数组是排序后的数组。

代码实现:

javascript

js 复制代码
<script>
// 选择排序的JavaScript程序实现
function swap(arr,xp, yp)
{
	var temp = arr[xp];
	arr[xp] = arr[yp];
	arr[yp] = temp;
}

function selectionSort(arr, n)
{
	var i, j, min_idx;
	// 逐个移动未排序子数组的边界
	for (i = 0; i < n-1; i++)
	{
    // 在未排序的数组中找到最小元素
		min_idx = i;
		for (j = i + 1; j < n; j++)
		if (arr[j] < arr[min_idx])
			min_idx = j;
		// 将找到的最小元素与第一个元素交换位置
		swap(arr,min_idx, i);
	}
}

function printArray( arr, size)
{
	var i;
	for (i = 0; i < size; i++)
		console.log(arr[i] + " ");
}

var arr = [64, 25, 12, 22, 11];
	var n = 5;
	selectionSort(arr, n);
	document.write("Sorted array: <br>");
	printArray(arr, n);
</script>

golang

go 复制代码
package main

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

type ArrT interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 | ~float32 | ~float64
}

// SelectSort 选择排序
func SelectSort[T ArrT](arr []T) []T {
	var length = len(arr)
	for i := 0; i < length-1; i++ {
		var minIndex = i
		for j := i + 1; j < length; j++ {
			if arr[minIndex] > arr[j] {
				minIndex = j
			}
		}
		arr[minIndex], arr[i] = arr[i], arr[minIndex]
	}

	return arr
}

func Test_SelectSort(t *testing.T) {
	var arr = []int{64, 25, 12, 22, 11}

	var except = []int{11, 12, 22, 25, 64}
	assert.Equal(t, except, SelectSort[int](arr))
}

输出

排序数组: 11 12 22 25 64

选择排序的复杂度分析

时间复杂度:选择排序的时间复杂度为O(N 2 ),因为有两个嵌套循环:

  • 一个循环逐一选择 Array 的元素 = O(N)
  • 另一个循环将该元素与每个其他数组元素进行比较 = O(N)
  • 因此总体复杂度 = O(N) * O(N) = O(N*N) = O(N 2 )

辅助空间: O(1),因为在交换数组中的两个值时,唯一使用的额外内存用于临时变量。选择排序不会进行超过 O(N) 的交换,并且在内存写入成本高昂时非常有用。

选择排序算法的优点

  • 简单易懂。
  • 适用于小型数据集。

选择排序算法的缺点

  • 在最坏和平均情况下,选择排序的时间复杂度为 O(n^2)。
  • 在大型数据集上效果不佳。
  • 不保留具有相同键的项目的相对顺序,这意味着它不稳定。

选择排序的常见问题

Q1. 选择排序算法稳定吗?

选择排序算法的默认实现并不稳定

Q2。选择排序算法是否到位?

是的,选择排序算法是一种原地算法,因为它不需要额外的空间。

相关推荐
xiaoshiguang32 小时前
LeetCode:222.完全二叉树节点的数量
算法·leetcode
爱吃西瓜的小菜鸡2 小时前
【C语言】判断回文
c语言·学习·算法
别NULL2 小时前
机试题——疯长的草
数据结构·c++·算法
TT哇2 小时前
*【每日一题 提高题】[蓝桥杯 2022 国 A] 选素数
java·算法·蓝桥杯
yuanbenshidiaos4 小时前
C++----------函数的调用机制
java·c++·算法
唐叔在学习4 小时前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
ALISHENGYA4 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
chengooooooo4 小时前
代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和
算法·leetcode·职场和发展
jackiendsc4 小时前
Java的垃圾回收机制介绍、工作原理、算法及分析调优
java·开发语言·算法
游是水里的游5 小时前
【算法day20】回溯:子集与全排列问题
算法