Go语言数据结构与算法-基础数据结构
因为要计划刷LeetCode了,虽然之前用C++刷过,但是我发现我学完go语言了,对里面的数据结构并没有很熟悉。遇到想要用的数据结构不知道怎么用,所以我在这里介绍一下Go语言中基础的数据结构怎么写。
数组/切片
最最基础的内容,可以使用var slice []int显示声明切片,注意此时显示声明的切片slice是nil值,而slice := []int{}中slice不为nil,即使切片为空。注意如果向参数传递切片,会改变切片,而传递数组则不会改变数组。
var arr [5]int //定长数组slice := []int{1,2,3} //动态切片
slice := append(slice,4) //扩容
链表
需要定义链表的结构,注意哈,这里的指针零值也是nil,和上面的切片的零值是一样的。我们可以定义双向链表,就是多加一个Pre指针,还有其他结构的链表,只需要修改数据结构即可。
type ListNode struct{Var intNext *ListNode //指针零值是nil
}head := &ListNode{Var: 0}
head.Next := &ListNode{Var: 1} type ListNodeNew struct{Var intNext *ListNodeNewPre *ListNodeNew
}
二叉树
除了普通二叉树之外,我们还可能用到多叉树,只需要定义指针数组即可。go语言中比较省事的就是不需要担心堆栈的问题,如果是C++,还需要从堆中申请内存。
type TreeNode{Var intLeft *TreeNodeRight *TreeNode
}head := &TreeNode{Var: 0}
head.Left := &TreeNode{Var: 1}
head.Right := &TreeNode{Var: 2}type NNode{Var intChildren []*NNode
}
栈/队列
以下都是基于切片实现的,不过还有双端队列,或者循环队列的数据结构,这里就不给出例子了,请读者自行实现。
//基于切片实现
stack := []int{} //空切片
stack := append(stack,6) //定义入栈
v := stack[len(stack)-1] //取栈顶内容
stack := stack[:len(stack)-1] //定义出栈queue := []int{}
queue := append(queue,6) //入队
v := queue[0] //取队首内容
queue := queue[1:] //出队
堆
这个重点不在于数据结构本身,而是堆的操作函数,可以使用type heap []int来定义堆(切片)。但是重点在于实现堆的方法。首先有大根堆还有小根堆,还有上浮下沉,交换等方法,大小根堆的实现还不一样。
哈希表
也就是map,在go语言中有该数据结构。通过map[key]value来定义,注意使用make的时候会进行初始化,也就是m不为nil,但是是一个空的哈希表,也可以使用m := map[string]int{}来初始化。
m := make(map[string]int) //定义哈希表的键值对的数据类型
m["key"] = 42 //添加键值对
value, exists := m["key"] //安全的取值
delete(m, "key") //删除键值对
集合
集合可以说是没有值的键值对,可以利用set := make(map[string]bool)来模拟集合,也就是bool来占位,但是没有什么作用。更好的方法是用空结构体struct{}
作为value,减少内存占用,因为空结构体不分配内存。
set := make(map[string]struct{})
// 添加元素
set["apple"] = struct{}{}
set["banana"] = struct{}{}// 检查元素是否存在
if _, exists := set["apple"]; exists {fmt.Println("apple exists")
}// 删除元素
delete(set, "banana")
好像还有图没有实现,可以用邻接矩阵,或者邻接表的方式实现,还有并查集、跳表、布隆过滤器这些数据结构。不过这几部分内容比较多,而且也比较难,只能放到后面再讲了。