排序能够说时最基础的算法之一,排序就是将数据按照某种逻辑从新排列的过程,好比从大到小排序、从小到大排序;排序很是常见好比有购物车物品的排序、历史订单的排序等等;算法咱们比较关心的主要有两点:时间复杂度与空间复杂度,排序算法同样;这篇文章只介绍几种基本的排序算法:冒泡排序、插入排序、选择排序;算法
算法逻辑上分为已排序未排序两个区间,从当前列表中选择最小的元素与当前列表第一个元素交换位置,从列表剩余元素中找到最小元素与列表第二个元素交换位置如此重复执行的算法为选择排序算法;
选择排序与数据的初始状态无关,每次查找最小元素值时都会与数组中元素进行交换位置,所以选择排序为非稳定排序算法,在各类状况下算法时间复杂度都为O(n2),空间复杂度为O(n);数组
func SelectionSort(data [] int) { n := len(data) if n <= 1 { return } for i := 0; i < n; i++ { //最小元素索引 min := i for j := i + 1; j < n; j++ { if data[j] < data[min] { min = j } } //交换元素,交换后未已排序数据 data[i], data[min] = data[min], data[i] } }
与选择排序相似在逻辑上列表分为已排序和未排序两个区间,初始时已排序区间未为左边第一个元素,插入排序的核心为从右边未排序区间中选择元素插入到左边合适的位置,直到已排序列表长度等于原始列表长度;插入排序算法的关键步骤为元素比较与元素的移动,当从未排序端拿数据插入到已排序端时已排序端可能会存在大量的数据移动;
与选择排序不一样的是列表初始状态对插入排序的性能影响很大,当列表初始状态有序度很高时插入排序并不须要大量移动数据,从中能够看出插入排序为原地排序算法、算法是稳定的;
算法最好状况下时间复杂度为:O(n)、平均、最坏复杂度为:O(n2);性能
func InsertionSort(data [] int) { n := len(data) for i := 1; i < n; i++ { value := data[i] //查找插入位置 var j int for j = i - 1; j >= 0; j-- { if data[j] > value { //数据后移 data[j+1] = data[j] } else { break } } data[j+1] = value } }
每次比较相邻两个元素是否知足,不然交换相邻两个元素,每次冒泡至少一个元素移动到它所属位置,重复N次完成列表排序;
冒泡操做核心为项链元素交换,空间复杂度为O(1),为原地排序算法;算法是稳定的,最好状况时间复杂度为为O(n),平均与最坏状况时间复杂度为:O(n2);3d
func BubbleSort(data [] int) { n := len(data) for i := 0; i < n; i++ { //是否有数据交换,用于当某轮中数据已排序时退出循环 flag := false for j := 0; j < n-1-i; j++ { if data[j] > data[j+1] { //冒泡 data[j], data[j+1] = data[j+1], data[j] flag = true } } if !flag { break } } }
参考资料: 《算法四》code