[ 排序算法实践 | 青训营笔记 ]

65 阅读2分钟

算法是学会一个程序基本语法之后要做得事,我个人所了解的基本算法有冒泡排序,插入排序,归并排序,堆排序,桶排序,快速排序 希尔排序,选择排序,计数排序,其中希尔排序是插入排序的进阶版,复杂度会略低一点。 计数排序会简单一些,计数排序是一个非基于比较的排序算法,对输入的数据有附加的限制条件: 1、输入的线性表的元素属于有限偏序集S; 2、设输入的线性表的长度为n,|S|=k(表示集合S中元素的总数目为k),则k=O(n)。 在这两个条件下,计数排序的复杂性为O(n)。 计数排序的基本思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数(此处并非比较各元素的大小,而是通过对元素值的计数和计数值的累加来确定)。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。 稳定性: 排序算法是稳定的,因为在确定最终有序序列而遍历原序列时,遍历的方式是自右往左,从而导致后面的元素一定是排在后面的。时间复杂度为 O ( n + k ) O(n+k) O(n+k),其中n为要排序的元素个数,k为data中最大的整数加1,空间复杂度为 O ( n + k ) O(n+k) O(n+k),其中n为要排序的元素个数,k为data中最大的整数加1。func Count(arr []*Data) { var index int = 0 //记录输入序列中待排序字段的最大值 var tmp_len int = 0 for _, data := range arr { if tmp_len < data.No { tmp_len = data.No } } tmp_len++ //创建数组,go不支持动态创建数组,因此用切片 //队列用[]Data切片来表示,因为可以根据索引做到先进先出 tmp_arr := make([][]*Data, tmp_len) for _, data := range arr { tmp_arr[data.No] = append(tmp_arr[data.No], data) } //按照数组的顺序取元素 for i := 0; i < tmp_len; i++ { if tmp_arr[i] != nil { for j := 0; j < len(tmp_arr[i]); j++ { arr[index] = tmp_arr[i][j] index++ } } } 我个人理解的计数排序就是把数转化为下标,不过计数排序适用于数据较密集的数据,因为如果其中某个数过大的话,转化为很大下标的数组会使得数据很分散,大量浪费空间。总而言之每个排序算法都有自己使用的环境,没有绝对的好和绝对的坏。