Go实现基本的排序和查找

 

一、基本排序

        (1)基于Big-O(n^2)的排序

                ①选择法排序  空间复杂度O(1), 不稳定

选择数组最小的元素,与数组第一个元素交换,然后选择剩余的数组元素中最小的元素,与数组第二个元素交换,一直重复上述操作,直到数组有序。


func selectionSort(arr []int){
    
    for i := 0; i < len(arr) - 1; i++ {    
        minIndex := i
        for j := i + 1; j < len(arr); j++ {
            if arr[minIndex] > arr[j] {
                minIndex = j
            }
        }
        swap(arr, i, minIndex)    
    }
}

func swap(arr []int, i int, j int){
    temp := arr[i]
    arr[i] = arr[j]
    arr[j] = temp
}

                ②冒泡法排序  空间复杂度O(1), 稳定

冒泡排序是一种比较简单的排序算法,它是一种基于比较的算法,是一种稳定的排序算法。从第一个元素开始,每次比较相邻元素,如果元素顺序不正确,则进行交换,否则,比较下一对相邻元素。重复上述过程,一直到所有元素都有序。

func bubbleSort(arr []int){

    for e := len(arr) - 1; e > 0; e-- {
        for i := 0; i < e; i++ {
            if arr[i] > arr[i + 1]{
                swap(arr []int, i, i + 1)
            }
        }
    }
}

                ③插入法排序              

func insertSort(arr []int){

    for i := 1; i < len(arr); i++ {
        for j := i - 1; j >= 0; j-- {
            if arr[j] > arr[j + 1]{
                swap(arr, j, j + 1)
            }
        }
    }
}

        (2)基于Big-O(n * log(n))的排序

                ①快速排序  空间复杂度O(log n), 不稳定

                        ① quickSort(arr []int, L int, R int); 运用了分而治之的思想 ,对partition操作之后对返回的数组的左边和右边继续分而治之,从局部有序到整体有序的过程。

                        ② partition(arr []int, L int, R int ) 思想就是比较,有less区域和more区域,less区 域都是小于参考值的,more区域都是大于参考值的。所以可以这样操作: 移动 L 和 more,L 从0 开始,满足条件往右移动, more从R开始满足条件往左移动。当 L < more 时 :(1)若 arr [L] < arr[R] { less++, swap(arr, less, L), L++} (2) 若arr [L] > arr[R] { more-- , swap(arr, more, L)} (3) 若arr[L] == arr[R] {L++}; ,最后返回partition的数组的下标。

import (
    "fmt"
    "math/rand"
    "time"
)

func quickSort(arr []int, L int, R int)  {
	if(L < R){
		lF, rF := float32(L), float32(R)
		rand.Seed(time.Now().UnixNano())
		randomIndex := int(lF + rand.Float32() * (rF - lF + 1))//数组中随机获取下标
		swap(arr, randomIndex, R)
		var p []int = partition(arr, L, R)    //partition操作返回p[0]和p[1]
		quickSort(arr, L, p[0] - 1)           //p[0]-1为随机下标对应的值的左边
		quickSort(arr, p[1] + 1, R)           //p[1]+1为随机下标对应的值的右边
	}
}

func partition(arr []int, L int, R int) []int {
	less, more := L - 1, R  //less区域为小于随机下标对应的值,more区域为大于随机下标对应的值
	for L < more {
		if arr[L] < arr[R] {
			less++
			swap(arr, less, L)
			L++
		} else if arr[L] > arr[R]{
			more--
			swap(arr, more, L)
		} else {
			L++
		}
	}
	swap(arr, more, R)
	return []int {less + 1, more}
}

                ②归并排序  空间复杂度O(n),稳定

                        ① process(arr []int, L int, R int); 递归使用了二分思想,即 (L, Mid) 进行merge,(Mid + 1, R)进行merge,最后整体(L, R) 进行merge 。

                        ② merge(arr []int, L int, Mid int, R int) 借助辅助空间,(L, Mid)和(Mid + 1, R)中谁小谁进辅助空间,辅助空间就形成局部有序,最后到整体有序。 


func mergeSort(arr []int, L int, Mid int, R int) {
	if len(arr) < 2 {
		return
	}

	help := make([]int, 0, R - L + 1)
	p1, p2 := L, Mid + 1

	for p1 <= Mid && p2 <= R {
		if arr[p1] <= arr[p2] {
			help = append(help, arr[p1])
			p1++
		} else {
			help = append(help, arr[p2])
			p2++
		}
	}
	for p1 <= Mid {
		help = append(help, arr[p1])
		p1++
	}
	for p2 <= R {
		help = append(help, arr[p2])
		p2++
	}

	for i := 0; i < len(help); i++ {
		arr[L + i] = help[i]
	}
}

                ③堆排序(优先队列)

                        ①heapInsert(arr []int, index int) 建立大根堆,(index * 2) + 1为该节点左孩子,(index * 2) + 2 为该节点右孩子,(index - 1) / 2 为该节点的父节点。若该节点大于父节点,就交换,并且index = (index - 1) / 2。

                        ②heapify(arr []int, index int, heapSize int), 找到最后一个节点lastNode,该节点与当前根节点交换,同时heap--,即最后位置上为最大值,根节点为极小值。此时从根结点出发,继续heapify的过程(左孩子右孩子较大者与根节点交换, lastNode节点 来到孩子节点较大者位置,继续左右孩子较大者比较,直至没有左右孩子)


func heapInsert(arr []int, index int){

	for arr[index] > arr[(index - 1) / 2] {

		swap(arr, index, (index - 1) / 2)
		index = (index - 1) / 2
	}
}

//index * 2 + 1  左孩子节点
//index * 2 + 2  右孩子节点
//(index - 1) / 2 父节点
func heapify(arr []int, index int, heapSize int){

	var largestIndex int
	leftNode := index * 2 + 1

	for leftNode < heapSize {

		if leftNode + 1 < heapSize && arr[leftNode + 1] > arr[leftNode] {
			largestIndex = leftNode + 1
		} else {
			largestIndex = leftNode
		}

		if arr[largestIndex] < arr[index] {
			largestIndex = index
		}
		if largestIndex == index {

			break
		}
		swap(arr, largestIndex, index)

		index = largestIndex

		leftNode = index * 2 + 1
	}

}

二、基本查找

        (1)基于Big-O(log(n))的查找

                ①二分查找

func binarySearch(nums []int, target int) int {
	left, right := 0, len(nums) - 1
	for left <= right {
		Mid := left + (right - left) >> 1
		if nums[Mid] == target {
			return Mid
		} else if nums[Mid] > target {
			right = Mid - 1
		} else {
			left = Mid + 1
		}
	}
	return left
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值