最常用的排序算法:快速排序 和 归并排序。 适用于数值范围较小或均匀分布:计数排序 和 桶排序。 适合小规模数据或者部分有序的数据:冒泡排序、选择排序 和 插入排序。
以下示例以从小到大排序为例
1、冒泡排序 和相邻的数比较,比它大交换,向左移动,直到列表的末尾,返回,重复过程
时间复杂度:o(n^2)
1 2 3 4 5 6 7 8 9 10 func bubbleSort (nums []int ) []int { for i:=0 ;i<len (nums);i++{ for j:=0 ;j<len (nums)-i-1 ;j++{ if nums[j]>nums[j+1 ]{ nums[j],nums[j+1 ]=nums[j+1 ],nums[j] } } } return nums }
2、选择排序 在未排序数组中选择一个最小的放到已经排序数组的最后面,重复过程
时间复杂度:o(n^2)
1 2 3 4 5 6 7 8 9 10 11 12 func choseSort (nums []int ) []int { for i:=0 ;i<len (nums);i++{ min:=i for j:=i+1 ;j<len (nums);j++{ if nums[j]<nums[min]{ min=j } } nums[i],nums[min]=nums[min],nums[i] } return nums }
3、插入排序 将未排序数组的第一个数和已经排序的数组元素依次比较,插入到合适的位置
时间复杂度:o(n^2)
1 2 3 4 5 6 7 8 9 10 11 12 func insertSort (nums []int ) []int { for i:=1 ;i<len (nums);i++{ cur:= nums[i] j := i - 1 for j >= 0 && nums[j] > current { nums[j+1 ]=nums[j] j-- } nums[j+1 ] = cur } return nums }
4、快速排序 选择一个基数,大的放右边,小的放左边,然后分别对左边和右边重复这样的操作
时间复杂度:o(nlog(n))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 func quickSort (nums []int ) []int { if len (nums)<=1 { return nums } base:=nums[len (nums)/2 ] l,r:=0 ,len (nums)-1 for l<=r{ for l<=r&&nums[l]<base{ l++ } for l<=r&&nums[r]>base{ r-- } if l<=r{ nums[l],nums[r]=nums[r],nums[l] l++ r-- } } quickSort(nums[:r+1 ]) quickSort(nums[l:]) return nums }
5、归并排序 将未排序数组划分两组,得到的两组继续递归操作,切半划分,直到划分的组不能被划分,合并两个数组,返回再合并
时间复杂度:o(nlog(n))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 func mergeSort (nums []int ) []int { size:=len (nums) if size<=1 { return nums } left:=mergeSort(nums[:size/2 ]) right:=mergeSort(nums[size/2 :]) return merge(left,right) } func merge (str1 []int ,str2 []int ) []int { res:=make ([]int ,0 ,len (str1)+len (str2)) i,j:=0 ,0 for i<len (str1)&&j<len (str2){ if str1[i]<str2[j]{ res=append (res,str1[i]) i++ }else { res=append (res,str2[j]) j++ } } for i<len (str1){ res=append (res,str1[i]) i++ } for j<len (str2){ res=append (res,str2[j]) j++ } return res }
6、堆排序 将未排序数组构建一个完全二叉树,找到倒数第一个非叶子节点(n/2-1),与子节点比较,交换比自己大的子节点, 构建一个大根堆,每次取第一个,直到取完(大根堆可以让空间复杂度降为 o(1))
时间复杂度:o(nlog(n))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 func heapSort (nums []int ) []int { if len (nums)<=1 { return nums } buidHeap(nums) res:=make ([]int ,0 ,len (nums)) for len (nums)>0 { val,newNums:=pop(nums) res=append (res,val) nums=newNums } return res } func buildHeap (nums []int ) { i:=len (nums)/2 -1 for i>=0 { adjustHeap(nums,i,len (nums)) i-- } } func adjustHeap (nums []int ,i int ,size int ) { maxIndex:=i left,right:=i*2 ,i*2 +1 if left<size &&nums[maxIndex]<nums[left]{ maxIndex=left } if i*2 +1 <size&&nums[maxIndex]<nums[right]{ maxIndex=right } if maxIndex!=i{ nums[i],nums[maxIndex]=nums[maxIndex],nums[i] adjustHeap(nums,maxIndex,size) } } func pop (nums []int ) (int ,[]int ) { top:=nums[0 ] nums[0 ]=nums[len (nums)-1 ] newNums:=nums[:len (nums)-1 ] adjustHeap(nums,0 ,len (newNums)) return top,newNums }
7、希尔排序 改进版的插入排序,跳着排,最后会间隔为 1 排
时间复杂度:o(n^(3/2))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 func shellSort (nums []int ) []int { if len (nums)<=1 { return nums } for gap:=len (nums)/2 ;gap>0 ;gap/=2 { for i:=gap;i<len (nums);i++{ cur:=nums[i] j:=i for j>=gap&&nums[j-gap]>cur{ nums[j]=nums[j-gap] j-=gap } nums[j]=cur } } return nums }
8、桶排序 分桶→桶内排序→合并,每个桶都有范围限制,将数据分到对应的桶中,对每个桶中的数据分别排序,然后合并每个桶的数据
时间复杂度:o(n*k)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 func bucketSort (nums []int ) []int { if len (nums)<=1 { return nums } minNum,maxNum:=nums[0 ],nums[0 ] for i:=0 ;i<len (nums);i++{ if nums[i]<minNum{ minNum=nums[i] } if nums[i]>maxNum{ maxNum=nums[i] } } bucketNum:=len (nums) bucketSize:=(maxNum-minNum)/bucketNum buckets:=make ([][]int ,bucketNum) for i:=0 ;i<len (nums);i++{ index:=(nums[i]-minNum)/bucketSize if index==bucketNum{ index=bucketNum-1 } buckets[index]=append (buckets[index],nums[i]) } res:=make ([]int ,0 ,len (nums)) for i:=0 ;i<bucketNum;i++{ sort.Ints(bucket[i]) res=append (res,bucket[i]...) } return res }
9、基数排序 跟桶排序很像,先根据个位的数字排序,然后根据十位,依次递推,直到该数组最大数的最高位
时间复杂度:O(n*k)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 func radixSort (nums []int ) { if len (nums)<=1 { return nums } maxNum:=nums[0 ] for i:=0 ;i<len (nums);i++{ if nums[i]>maxNum { maxNum=nums[i] } } maxDigit := int (math.log10(float64 (maxNum))) + 1 for i:=0 ;i<maxDigit;i++{ bucket:=make ([][]int ,10 ) for j:=0 ;j<len (nums);j++{ digit := (nums[j] / int (math.Pow10(i))) % 10 bucket[digit]=append (bucket[digit],nums[j]) } nums=nil for j:=0 ;j<10 ;j++{ nums=append (nums,bucket[j]...) } } return nums }
10、计数排序 统计待排数组中每个元素的个数,然后对其进行合并
时间复杂度:O(n + k)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 func countingSort (nums []int ) []int { if len (nums)<=1 { return nums } minNum,maxNum:=nums[0 ],nums[0 ] for i:=0 ;i<len (nums);i++{ if nums[i]<minNum{ minNum=nums[i] } if nums[i]>maxNum{ maxNum=nums[i] } } counts:=make ([]int ,maxNum-minNum+1 ) for i:=0 ;i<len (nums);i++{ counts[nums[i]-minNum]++ } res:=make ([]int ,0 ,len (nums)) for i:=0 ;i<len (counts);i++{ for count[i]>0 { res=append (res,i+minNum) count[i]-- } } return res }