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。选择排序算法是否到位?

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

相关推荐
我是哈哈hh1 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
Tisfy1 小时前
LeetCode 2187.完成旅途的最少时间:二分查找
算法·leetcode·二分查找·题解·二分
Mephisto.java1 小时前
【力扣 | SQL题 | 每日四题】力扣2082, 2084, 2072, 2112, 180
sql·算法·leetcode
robin_suli1 小时前
滑动窗口->dd爱框框
算法
丶Darling.1 小时前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树
labuladuo5202 小时前
Codeforces Round 977 (Div. 2) C2 Adjust The Presentation (Hard Version)(思维,set)
数据结构·c++·算法
jiyisuifeng19912 小时前
代码随想录训练营第54天|单调栈+双指针
数据结构·算法
꧁༺❀氯ྀൢ躅ྀൢ❀༻꧂2 小时前
实验4 循环结构
c语言·算法·基础题
新晓·故知2 小时前
<基于递归实现线索二叉树的构造及遍历算法探讨>
数据结构·经验分享·笔记·算法·链表
总裁余(余登武)3 小时前
算法竞赛(Python)-万变中的不变“随机算法”
开发语言·python·算法