go算法

我们的排序有稳定和不稳定之分。稳定排序的意思是:比如原本一组无序的元素中出现两个相同的值,那么经过稳定排序后这两个相等的元素必然相邻,不改变原来无序状态下的先后顺序叫稳定的排序。(不懂我这样说明白了没有,下面给个例子)那么不稳定排序就是,原本相等的元素之间的顺序经过不稳定的排序后顺序随机,有可能保持原来的,有可能是打乱的。


选择排序的基本思想是:如果有N个元素需要排序,那么首先从N个元素中找到最小的那个元素与第0位置上的元素交换(说明一点,如果没有比原本在第0位置上的元素小的就不用交换了,后面的同样是),然后再从剩下的N-1个元素中找到最小的元素与第1位置上的元素交换,之后再从剩下的N-2个元素中找到最小的元素与第2位置上的元素交换,…直到所有元素都排序好(也就是直到从剩下的2个元素中找到最小的元素与第N-2位置上的元素交换)。


1.选择排序 时间复杂度:n的平方 空间复杂度:1

package main
import "fmt"

//选择排序
func SelectionSort(s []int)  {
    l := len(s) //以免每次循环判断都运算
    m := len(s)-1
    for i:=0;i<m;i++ {
        k:=i
        for j:=i+1;j<l;j++ {
            if s[j]<s[k] {
                k = j
            }
        }
        if k!=i {
            s[k],s[i] = s[i],s[k]
        }
    }
}

func main(){
	s := []int{9,0,6,5,8,2,1,7,4,3}
	fmt.Println(s)
	SelectionSort(s)
	fmt.Println(s)
}

插入排序的思想就是:从数组的下标为0的元素出发,每次向后取一个元素,将该元素插入到前面已排好的子数组中,以排升序为例,将所要插入的元素插在左边小于该元素和右边大于该元素之间的位置,进而形成新的子数组,直到所有元素全插进来为止。
2.插入排序 时间复杂度:O(n^2),空间复杂度:1

package main
import "fmt"

//插入排序
func InsertionSort(s []int) {
	n := len(s)
	if n < 2 {
		return
	}
	for i := 1; i < n; i++ {
		for j := i; j > 0 && s[j] < s[j - 1]; j-- {
			s[j],s[j-1] = s[j-1],s[j]
		}
	}
}
 
func main(){
	s := []int{9,0,6,5,8,2,1,7,4,3}
	fmt.Println(s)
	InsertionSort(s)
	fmt.Println(s)
}

3.二分查找:首先了解二分查找,首先在长度为n的表范围中查找,第一次循环在n/2中查找,第二次在n/2/2中查找,依次循环。假设在第X次找到,那么 就是找2的X次方次,有2的X次方=n解出x为log2的n ,故时间复杂度为log2N。由于辅助空间是常数级别的所以:空间复杂度是O(1);
思路:先找到中间的下标middle = (leftIndex + RightIndex) /2 ,然后让中间的下标值和FindVal比较
a:如果arr[middle] > FindVal,那么就向LeftIndex~(midlle - 1)区间找
b:如果arr[middle] < FindVal,那么就向middle + 1 ~RightIndex区间找
c:如果arr[middle] == FindVal,那么直接返回
②从①的a、b、c递归执行,知道找到位置
③如果LeftIndex > RightIndex,则表示找不到,退出

//代码
package main
import (
    "fmt"
)

//二分查找函数 //假设有序数组的顺序是从小到大(很关键,决定左右方向)
func BinaryFind(arr *[]int, leftIndex int , rightIndex int, findVal int) {
    //判断leftIndex是否大于rightIndex
    if leftIndex > rightIndex {
        fmt.Println("没找到")
        return 
    }
    
    //先找到中间的下标
    middle := (leftIndex + rightIndex) / 2 

    if (*arr)[middle] > findVal {  
        BinaryFind(arr, leftIndex, middle - 1, findVal)
    } else if (*arr)[middle] < findVal {
        BinaryFind(arr, middle + 1, rightIndex, findVal)
    } else {
        fmt.Printf("找到了,下标是%v\n", middle)
    }
}


func main() {
    //定义一个数组
    arr := []int{1, 2, 5, 7, 15, 25, 30, 36, 39, 51, 67, 78, 80, 82, 85, 91, 92, 97}
    BinaryFind(&arr, 0, len(arr) - 1, 30)
}

4.反转单链表

package main

import "fmt"

type node struct {
    value    int
    nextNode *node
}

func reverseNode(head *node) *node {
//  先声明两个变量
//  前一个节点
    var preNode *node
    preNode = nil
//  后一个节点
    nextNode := new(node)
    nextNode = nil
    for head != nil {
        //  保存头节点的下一个节点,
        nextNode = head.nextNode
        //  将头节点指向前一个节点
        head.nextNode = preNode
        //  更新前一个节点
        preNode = head
        //  更新头节点
        head = nextNode
    }
    return preNode
}

func printNode(head *node) {
    for head != nil {
        //fmt.Print(head.value, "\t")
        fmt.Println(head)
        head = head.nextNode
    }
    fmt.Println()
}

func main() {
    node1 := new(node)
    node1.value = 1
    node2 := new(node)
    node2.value = 2
    node3 := new(node)
    node3.value = 3
    node4 := new(node)
    node4.value = 4
    node1.nextNode = node2
    node2.nextNode = node3
    node3.nextNode = node4
    printNode(node1)

    head := reverseNode(node1)
    printNode(head)
}

冒泡排序顾名思义就是整个过程像气泡一样往上升,单向冒泡排序的基本思想是(假设由小到大排序):对于给定n个记录,从第一个记录开始依次对相邻的两个记录进行比较,当前面的记录大于后面的记录时,交换位置,进行一轮比较和换位后,n个记录的最大记录将位于第n位,然后对前(n-1)个记录进行第二轮比较;重复该过程,直到记录剩下一个为止。


5.冒泡排序 时间复杂度:n平方,空间复杂度:1

//BubbleSort.go

package main

import "fmt"

func main() {
    values := []int{4, 93, 84, 85, 80, 37, 81, 93, 27,12}
    fmt.Println(values)
    BubbleAsort(values)
    BubbleZsort(values)
}

func BubbleAsort(values []int) {
    for i := 0; i < len(values)-1; i++ {
        for j := i+1; j < len(values); j++ {
            if  values[i]>values[j]{
                values[i],values[j] = values[j],values[i]
            }
        }
    }
    fmt.Println(values)
}

它的核心思想就是选取一个基准元素(通常已需要排序的数组第一个数),然后通过一趟排序将比基准数大的放在右边,比基准数小的放在左边,接着对划分好的两个数组再进行上述的排序。
6.快速排序:时间复杂度nlogN,最坏是n平方

package main

import "fmt"

func quickSort(arr []int, start, end int) {
    if start < end {
        i, j := start, end
        key := arr[(start+end)/2]
        for i <= j {
            for arr[i] < key {
                i++
            }
            for arr[j] > key {
                j--
            }
            if i <= j {
                arr[i], arr[j] = arr[j], arr[i]
                i++
                j--
            }
        }

        if start < j {
            quickSort(arr, start, j)
        }
        if end > i {
            quickSort(arr, i, end)
        }
    }
}

func main() {
    arr := []int{3, 7, 9, 8, 38, 93, 12, 222, 45, 93, 23, 84, 65, 2}
    quickSort(arr, 0, len(arr)-1)
    fmt.Println(arr)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值