赞
踩
作为一个程序员在谈到算法
这个词的时候,第一反应就是那些令人头疼的LeetCode题目,那本篇文章我们就讲讲程序员几个基础排序算法。
复杂度对比图
left > right
就交换的位置。动图解析
代码实现
func Bubble(arr []int) { for i := 0; i len(arr); i++ { // 冒泡是每次相邻的2个元素排 for j := 0; j len(arr)-1-i; j++ { if arr[j] > arr[j+1] { arr[j], arr[j+1] = arr[j+1], arr[j] } } }}
代码实现
// 选择排序 O(n^2)func Selection(arr []int) { // 这里的减一是因为需要通过下标方法元素 元素下标是从0开始的 // 假设mid是最小值,然后和后面元素进行比较 // 如果发现有比mid小的元素,就更新mid坐标 for i := 0; i len(arr)-1; i++ { min := i for j := i + 1; j len(arr); j++ { if arr[min] > arr[j] { min = j } } // 一轮结束之后交换2个元素位置 arr[i], arr[min] = arr[min], arr[i] }}
动图解析
代码实现
func Insertion(numbers []int) { for i := 1; i len(numbers); i++ { pervIndex := i - 1 current := numbers[i] // 用上一个元素比较当前的元素 for pervIndex >= 0 && numbers[pervIndex] > current { numbers[pervIndex+1] = numbers[pervIndex] // 向左移动方便下次比较 pervIndex -= 1 } // 如果pervIndex没有变化说明就不需要操作 if pervIndex+1 != i { numbers[pervIndex+1] = current } }}
动图解析
代码实现
// 希尔排序 O(n log n)func Shell(arr []int) { var pervIndex, current int // 1.先把原数据安装自定义步长分组 for gap := len(arr) / 2; gap > 0; gap /= 2 { // 2.然后分好组的数据进行选择排序 for i := gap; i len(arr); i++ { // 希尔排序 pervIndex = i - gap current = arr[i] for pervIndex >= 0 && arr[pervIndex] > current { arr[pervIndex+gap] = arr[pervIndex] pervIndex -= gap } if pervIndex+gap != i { arr[pervIndex+gap] = current } } }}
// https://zh.wikipedia.org/wiki/%E9%9A%8E%E4%B9%98func factorial(n int) int { if n == 1 { return 1 } return n * factorial(n-1)}
分治法(Divide and Conquer)
的一个非常典型的应用。动图解析
1.代码实现
package me.ibyte.algorithm.sort;import me.ibyte.algorithm.Sort;import java.util.Arrays;// Go写多了换Java写一些 思路和逻辑是一样的public class MergeSort implements Sort { public Integer[] sort(Integer[] arr) { // 取到中轴 分组 int middle = arr.length / 2; if (arr.length 2) { return arr; } // 通过中轴分左右组 Integer[] left = Arrays.copyOfRange(arr, 0, middle); Integer[] right = Arrays.copyOfRange(arr, middle, arr.length); // 重复分组 直到不能分组为止并且进行小块归并排序 return merge(sort(left), sort(right)); } private Integer[] merge(Integer[] left, Integer[] right) { // 存放排序好的零时数组 Integer[] result = new Integer[left.length + right.length]; int i = 0; // 不为空就进行排序 while (left.length != 0 && right.length != 0) { if (left[0] <= right[0]) { result[i++] = left[0]; // 排好的就减去 left = Arrays.copyOfRange(left, 1, left.length); } else { result[i++] = right[0]; right = Arrays.copyOfRange(right, 1, right.length); } } // 检测剩下的 while (left.length != 0) { result[i++] = left[0]; left = Arrays.copyOfRange(left, 1, left.length); } while (right.length != 0) { result[i++] = right[0]; right = Arrays.copyOfRange(right, 1, right.length); } return result; }}
源代码查看地址源代码
2.Golang实现就想尝试一下go特性高阶函数
func mergeSort(arr []int) []int { var result []int if len(arr) 2 { return arr } middle := len(arr) / 2 // 注意这是切片 切取的时候是包左 不包右 left := arr[:middle] right := arr[middle:] return func(left, right []int) []int { // 分组不能保证左右各组数据个数是一样的 for len(left) != 0 && len(right) != 0 { if left[0] <= right[0] { result = append(result, left[0]) left = left[1:] } else { result = append(result, right[0]) right = right[1:] } } for len(left) != 0 { result = append(result, left[0]) // 不断减小剩下的 left = left[1:] } for len(right) != 0 { result = append(result, right[0]) right = right[1:] } return result }(mergeSort(left), mergeSort(right))}
分治法(Divide and Conquer)
的一个非常典型的应用。pivot
。(partition)
操作。(recursive)
把小于基准值元素的子数列和大于基准值元素的子数列排序。视频解析
代码实现
package me.ibyte.algorithm.sort;import me.ibyte.algorithm.Sort;// https://www.bilibili.com/video/BV1at411T75o?zwpublic class QuickSort implements Sort { @Override public Integer[] sort(Integer[] arr) { return quickSort(arr,0,arr.length-1); } private Integer[] quickSort(Integer[] arr, int left, int right) { if (left >= right) { return arr; } // L记录开始位置 R记录尾巴位置 int pivot = arr[left],L=left,R=right; while(left while (left = pivot){ right--; } arr[left] = arr[right]; while(left left++; } arr[right] = arr[left]; } arr[left] = pivot; // L =0 left = 是中心轴值的位置 -1 分左右作用 quickSort(arr,L,left-1); quickSort(arr,left+1,R); return arr; }}
根据个人电脑配置不同耗时不同!!!随机数据范围是:rand.Intn(99999) - 9999)
测试过程中包含了随机数生成逻辑代码,所有算法速度应该减去随机数生成耗时(实际时间应该更短)。
算法 | 数量积 | 时间 |
---|---|---|
冒泡 | 10万 | 14.118 seconds |
选择 | 10万 | 8.862 seconds |
插入 | 10万 | 1.69 seconds |
希尔 | 10万 | 0.25 seconds |
希尔 | 100万 | 0.509 seconds |
希尔 | 1000万 | 3.314 seconds |
希尔 | 1亿 | 40s 左右(5次重复测试结果) |
归并 | 100万 | 0.752 seconds |
快速 | 100万 | 0.109 seconds |
测试源代码链接查看源代码,别忘了star
?。
相关的链接
- https://github.com/higker/go-algorithm
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。