简介
冒泡排序:两两比较相邻的数,如果反序则进行交换,知道没有反序为止,冒泡排序是一种稳定的排序算法。
选择排序:通过不断交换,每次遍历在n-i+1中选取数字最小的作为有序排列的第i个数,就是将每一趟最小的和第i进行交换。选择排序是一种稳定的排序算法。
插入排序:将一个数组分为有序和无须,将一个数插入到已经排好序的有序数组中,从而达到最终的排序。插入排序是一种稳定的排序算法。
希尔排序:希尔排序是在选择排序基础上改进的,希尔排序将一个数组分割成若干个子序列,然后对每个子序列进行插入排序,当每个子序列都基本有序时,最后在进行一次插入排序。主要将相聚某个增量的数组成一个子序列,这样就能保证在子序列内分别进行插入排序;希尔排序是不稳定的排序算法。
堆排序:每个节点的值大于或等于左右节点的称为大顶堆,每个节点值小于或等于左右节点的称为小顶堆。将待排序的数组构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点,然后将其与堆数组的末尾元素交换,此时末尾元素就是最大值,然后将剩余n-1个数重新构造成一个堆,如此反复。堆排序不是稳定的排序算法。
归并排序:将数组看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或1的有序子序列,在两两归并,如此重复,直到长度为n的有序序列为止。归并排序是一种稳定的排序算法。
快速排序:通过一趟排序将带排序记录分割成独立的两部分,其中一部分的数比另一部分数小,则可分别对这两部分数继续排序。
复杂度
平均情况 | 最好情况 | 最坏情况 | 辅助空间 | |
---|---|---|---|---|
冒泡排序 | O(n^2) | O(n) | O(n^2) | O(1) |
选择排序 | O(n^2) | O(n) | O(n^2) | O(1) |
插入排序 | O(n^2) | O(n) | O(n^2) | O(1) |
希尔排序 | O(nlogn)~O(n^2) | O(n^1.3) | O(n^2) | O(1) |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) |
快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(logn)~O(n) |
冒泡排序
func mp1(nums []int) {
n := len(nums)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
if nums[j] < nums[i] {
nums[i], nums[j] = nums[j], nums[i]
}
}
}
fmt.Println("冒泡1:", nums)
}
冒泡排序改进版
func mp2(nums []int) {
n := len(nums)
for i := 0; i < n; i++ {
for j := n - 2; j >= 0; j-- {
if nums[j] > nums[j+1] {
nums[j], nums[j+1] = nums[j+1], nums[j]
}
}
}
fmt.Println("冒泡2:", nums)
}
选择排序
func xz(nums []int) {
n := len(nums)
for i := 0; i < n; i++ {
min := i
for j := i + 1; j < n; j++ {
if nums[min] > nums[j] {
min = j
}
}
if min != i {
nums[i], nums[min] = nums[min], nums[i]
}
}
fmt.Println("选择: ", nums)
}
插入排序
func cr(nums []int) {
n := len(nums)
for i := 1; i < n; i++ {
tmp := nums[i]
j := i - 1
for ; j >= 0 && tmp < nums[j]; j-- {
nums[j+1] = nums[j]
}
if j+1 != i {
nums[j+1] = tmp
}
}
fmt.Println("插入排序:", nums)
}
希尔排序
func xe(nums []int) {
n := len(nums)
incr := n
for incr > 0 {
incr = incr / 3
for i := incr; i < n; i++ {
tmp := nums[i]
j := i - incr
for ; j >= 0 && tmp < nums[j]; j -= incr {
nums[j+incr] = nums[j]
}
if j+incr != i {
nums[j+incr] = tmp
}
}
}
fmt.Println("希尔排序:", nums)
}
归并排序
func gb(nums []int) {
msort(nums, 0, len(nums)-1)
fmt.Println("归并: ", nums)
}
func msort(nums []int, left, right int) {
mid := 0
tmp := make([]int, len(nums))
if left < right {
mid = (left + right) / 2
msort(nums, left, mid)
msort(nums, mid+1, right)
merge(tmp, nums, left, mid, right)
}
}
func merge(tmp, nums []int, left, mid, right int) {
l := left
r := mid + 1
k := left
for ; l <= mid && r <= right; k++ {
if nums[l] < nums[r] {
tmp[k] = nums[l]
l++
} else {
tmp[k] = nums[r]
r++
}
}
for ; l <= mid; l++ {
tmp[k] = nums[l]
k++
}
for ; r < right; r++ {
tmp[k] = nums[r]
k++
}
for left < k {
nums[left] = tmp[left]
left++
}
}
大顶堆
func swap(a, b *int) {
*a, *b = *b, *a
}
func maxHeap(nums []int) {
n := len(nums)
for i := n; i > 1; i-- {
createHeap(nums, i)
swap(&nums[0], &nums[i-1])
}
fmt.Println("大顶堆排序2:", nums)
}
func createHeap(nums []int, n int) {
for i := n/2 - 1; i >= 0; i-- {
heapAdjust(nums, i, n)
}
}
func heapAdjust(nums []int, m, n int) {
max := m
l := m*2 + 1
r := m*2 + 2
if l < n && nums[l] < nums[max] {
max = l
}
if r < n && nums[r] < nums[max] {
max = r
}
if m != max {
swap(&nums[m], &nums[max])
heapAdjust(nums, m, n)
}
}
小顶堆
func swap(a, b *int) {
*a, *b = *b, *a
}
func minHeap(nums []int) {
n := len(nums)
for i := n; i > 1; i-- {
CreateHeap(nums, i)
swap(&nums[0], &nums[i-1])
}
fmt.Println("小顶堆排序:", nums)
}
func CreateHeap(nums []int, n int) {
for i := n/2 - 1; i >= 0; i-- {
HeapAdjust(nums, i, n)
}
}
func HeapAdjust(nums []int, m int, n int) {
min := m
l := m*2 + 1
r := m*2 + 2
if l < n && nums[l] > nums[min] {
min = l
}
if r < n && nums[r] > nums[min] {
min = r
}
if m != min {
swap(&nums[m], &nums[min])
HeapAdjust(nums, m, n)
}
}
快速排序
func swap(a, b *int) {
*a, *b = *b, *a
}
func quickSort(nums []int) {
qsort(nums, 0, len(nums)-1)
fmt.Println("快速排序:", nums)
}
func qsort(nums []int, left, right int) {
if left < right {
p := partition(nums, left, right)
qsort(nums, left, p)
qsort(nums, p+1, right)
}
}
func partition(nums []int, left, right int) int {
tmp := nums[left]
for left < right {
for left < right && nums[right] > tmp {
right--
}
swap(&nums[left], &nums[right])
for left < right && nums[left] < tmp {
left++
}
swap(&nums[left], &nums[right])
}
return left
}
案例
求topk
func topK(nums []int, k int) {
res := Qsort(nums, 0, len(nums)-1, k)
fmt.Println(res, nums[:k])
}
func Qsort(nums []int, left, right, k int) int {
// n := len(nums)
for {
indx := Partition(nums, left, right)
if indx == k-1 {
return nums[indx]
} else if indx < k-1 {
left = indx + 1
} else {
right = indx - 1
}
}
}
func Partition(nums []int, left, right int) int {
tmp := nums[left]
for left < right {
for left < right && nums[right] <= tmp {
right--
}
nums[left] = nums[right]
for left < right && nums[left] >= tmp {
left++
}
nums[right] = nums[left]
}
nums[left] = tmp
return left
}
最大的k个数
func q1(nums []int, k int) {
q2(nums, 0, len(nums)-1, k)
fmt.Println(nums[:k])
}
func q2(nums []int, left, right, k int) {
m := q3(nums, left, right)
num := m - left + 1
if k < num {
q2(nums, left, m-1, k)
} else if k > num {
q2(nums, m+1, right, k-num)
}
}
func q3(nums []int, left, right int) int {
tmp := nums[right]
i := left - 1
for j := left; j < right; j++ {
if nums[j] >= tmp { //改成<=就是求最小的k个数
i++
nums[i], nums[j] = nums[j], nums[i]
}
}
nums[i+1], nums[right] = nums[right], nums[i+1]
return i + 1
}