目录
(四)二叉搜索树、平衡二叉树、红黑树、哈夫曼树、前缀树的理解
一、排序算法
(一)快速排序
快速排序是一种高效的排序算法,它采用分治的思想,通过选择一个基准元素,将数组分为两部分,小于基准元素的部分和大于基准元素的部分,然后分别对这两部分进行递归排序。
package main
func quickSort(arr []int) []int {
if len(arr) <= 1 {
return arr
}
pivot := arr[len(arr)-1]
left := []int{}
right := []int{}
for _, v := range arr[:len(arr)-1] {
if v < pivot {
left = append(left, v)
} else {
right = append(right, v)
}
}
return append(append(quickSort(left), pivot), quickSort(right)...)
}
(二)归并排序
归并排序也是一种分治算法,它将数组分成两个子数组,分别对两个子数组进行排序,然后将两个有序的子数组合并成一个有序的数组。
package main
func mergeSort(arr []int) []int {
if len(arr) <= 1 {
return arr
}
mid := len(arr) / 2
left := mergeSort(arr[:mid])
right := mergeSort(arr[mid:])
return merge(left, right)
}
func merge(left, right []int) []int {
result := []int{}
i, j := 0, 0
for i < len(left) && j < len(right) {
if left[i] < right[j] {
result = append(result, left[i])
i++
} else {
result = append(result, right[j])
j++
}
}
result = append(result, left[i:]...)
result = append(result, right[j:]...)
return result
}
(三)冒泡排序
冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
package main
func bubbleSort(arr []int) []int {
n := len(arr)
for i := 0; i < n-1; i++ {
for j := 0; j < n-i-1; j++ {
if arr[j] > arr[j+1] {
arr[j], arr[j+1] = arr[j+1], arr[j]
}
}
}
return arr
}
(四)插入排序
插入排序是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
package main
func insertionSort(arr []int) []int {
n := len(arr)
for i := 1; i < n; i++ {
key := arr[i]
j := i - 1
for j >= 0 && arr[j] > key {
arr[j+1] = arr[j]
j--
}
arr[j+1] = key
}
return arr
}
二、数据结构实现
(一)LRU 缓存
LRU(Least Recently Used)缓存是一种最近最少使用的缓存淘汰策略。当缓存满时,会淘汰最近最少使用的元素。
package main
import "container/list"
type LRUCache struct {
capacity int
list *list.List
items map[int]*list.Element
}
type pair struct {
key int
value int
}
func NewLRUCache(capacity int) *LRUCache {
return &LRUCache{
capacity: capacity,
list: list.New(),
items: make(map[int]*list.Element),
}
}
func (c *LRUCache) Get(key int) int {
if elem, ok := c.items[key]; ok {
c.list.MoveToFront(elem)
return elem.Value.(*pair).value
}
return -1
}
func (c *LRUCache) Put(key int, value int) {
if elem, ok := c.items[key]; ok {
c.list.MoveToFront(elem)
elem.Value.(*pair).value = value
} else {
if len(c.items) >= c.capacity {
lastElem := c.list.Back()
delete(c.items, lastElem.Value.(*pair).key)
c.list.Remove(lastElem)
}
newElem := c.list.PushFront(&pair{key, value})
c.items[key] = newElem
}
}
(二)哈希表
哈希表是一种根据关键码值(Key value)而直接进行访问的数据结构。
package main
type HashTable struct {
buckets []*list.List
size int
}
type entry struct {
key string
value interface{}
}
func NewHashTable(size int) *HashTable {
ht := &HashTable{
buckets: make([]*list.List, size),
size: size,
}
for i := range ht.buckets {
ht.buckets[i] = list.New()
}
return ht
}
func (h *HashTable) hash(key string) int {
hash := 0
for _, char := range key {
hash += int(char)
}
return hash % h.size
}
func (h *HashTable) Put(key string, value interface{}) {
index := h.hash(key)
list := h.buckets[index]
for e := list.Front(); e!= nil; e = e.Next() {
if e.Value.(*entry).key == key {
e.Value.(*entry).value = value
return
}
}
list.PushBack(&entry{key, value})
}
func (h *HashTable) Get(key string) interface{} {
index := h.hash(key)
list := h.buckets[index]
for e := list.Front(); e!= nil; e = e.Next() {
if e.Value.(*entry).key == key {
return e.Value.(*entry).value
}
}
return nil
}
(三)基于数组的栈
栈是一种后进先出(LIFO)的数据结构。
package main
type ArrayStack struct {
items []interface{}
top int
}
func NewArrayStack(capacity int) *ArrayStack {
return &ArrayStack{
items: make([]interface{}, capacity),
top: -1,
}
}
func (s *ArrayStack) Push(item interface{}) {
if s.top == len(s.items)-1 {
panic("Stack is full")
}
s.top++
s.items[s.top] = item
}
func (s *ArrayStack) Pop() interface{} {
if s.top == -1 {
panic("Stack is empty")
}
item := s.items[s.top]
s.top--
return item
}
func (s *ArrayStack) IsEmpty() bool {
return s.top == -1
}
(四)基于优先队列的最小堆
最小堆是一种完全二叉树,每个节点的值都小于或等于其子节点的值。
package main
type MinHeap struct {
items []int
}
func NewMinHeap() *MinHeap {
return &MinHeap{}
}
func (h *MinHeap) Insert(item int) {
h.items = append(h.items, item)
h.heapifyUp(len(h.items) - 1)
}
func (h *MinHeap) ExtractMin() int {
if len(h.items) == 0 {
return -1
}
min := h.items[0]
h.items[0] = h.items[len(h.items)-1]
h.items = h.items[:len(h.items)-1]
h.heapifyDown(0)
return min
}
func (h *MinHeap) heapifyUp(index int) {
for index > 0 {
parentIndex := (index - 1) / 2
if h.items[parentIndex] <= h.items[index] {
break
}
h.items[parentIndex], h.items[index] = h.items[index], h.items[parentIndex]
index = parentIndex
}
}
func (h *MinHeap) heapifyDown(index int) {
for {
leftChildIndex := 2*index + 1
rightChildIndex := 2*index + 2
smallest := index
if leftChildIndex < len(h.items) && h.items[leftChildIndex] < h.items[smallest] {
smallest = leftChildIndex
}
if rightChildIndex < len(h.items) && h.items[rightChildIndex] < h.items[smallest] {
smallest = rightChildIndex
}
if smallest == index {
break
}
h.items[index], h.items[smallest] = h.items[smallest], h.items[index]
index = smallest
}
}
三、链表操作
(一)反转单链表
反转一个单链表,即将链表的节点顺序反转。
package main
type ListNode struct {
Val int
Next *ListNode
}
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
curr := head
for curr!= nil {
next := curr.Next
curr.Next = prev
prev = curr
curr = next
}
return prev
}
(二)找出两个单链表的交点
给定两个单链表,判断它们是否有交点,如果有,返回交点的节点。
package main
func getIntersectionNode(headA, headB *ListNode) *ListNode {
if headA == nil || headB == nil {
return nil
}
pA, pB := headA, headB
for pA!= pB {
if pA == nil {
pA = headB
} else {
pA = pA.Next
}
if pB == nil {
pB = headA
} else {
pB = pB.Next
}
}
return pA
}
(三)检测单链表中是否有环
判断一个单链表中是否存在环。
package main
func hasCycle(head *ListNode) bool {
if head == nil {
return false
}
slow, fast := head, head
for fast!= nil && fast.Next!= nil {
slow = slow.Next
fast = fast.Next.Next
if slow == fast {
return true
}
}
return false
}
四、树的操作
(一)判断二叉树是否平衡
判断一棵二叉树是否是平衡二叉树,即该二叉树的任意节点的左右子树高度差不超过 1。
package main
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func isBalanced(root *TreeNode) bool {
return height(root)!= -1
}
func height(node *TreeNode) int {
if node == nil {
return 0
}
leftHeight := height(node.Left)
if leftHeight == -1 {
return -1
}
rightHeight := height(node.Right)
if rightHeight == -1 {
return -1
}
if abs(leftHeight-rightHeight) > 1 {
return -1
}
return max(leftHeight, rightHeight) + 1
}
func abs(a int) int {
if a < 0 {
return -a
}
return a
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
(二)二叉树的遍历
- 前序遍历:先访问根节点,然后遍历左子树,最后遍历右子树。
- 中序遍历:先遍历左子树,然后访问根节点,最后遍历右子树。
- 后序遍历:先遍历左子树,然后遍历右子树,最后访问根节点。
package main
func preOrderTraversal(root *TreeNode) []int {
result := []int{}
if root == nil {
return result
}
result = append(result, root.Val)
result = append(result, preOrderTraversal(root.Left)...)
result = append(result, preOrderTraversal(root.Right)...)
return result
}
func inOrderTraversal(root *TreeNode) []int {
result := []int{}
if root == nil {
return result
}
result = append(result, inOrderTraversal(root.Left)...)
result = append(result, root.Val)
result = append(result, inOrderTraversal(root.Right)...)
return result
}
func postOrderTraversal(root *TreeNode) []int {
result := []int{}
if root == nil {
return result
}
result = append(result, postOrderTraversal(root.Left)...)
result = append(result, postOrderTraversal(root.Right)...)
result = append(result, root.Val)
return result
}
(三)二叉树的层序遍历
按层次遍历二叉树,即从根节点开始,依次遍历每一层的节点。
package main
func levelOrder(root *TreeNode) [][]int {
result := [][]int{}
if root == nil {
return result
}
queue := []*TreeNode{root}
for len(queue) > 0 {
levelSize := len(queue)
levelValues := []int{}
for i := 0; i < levelSize; i++ {
node := queue[0]
queue = queue[1:]
levelValues = append(levelValues, node.Val)
if node.Left!= nil {
queue = append(queue, node.Left)
}
if node.Right!= nil {
queue = append(queue, node.Right)
}
}
result = append(result, levelValues)
}
return result
}
(四)二叉搜索树、平衡二叉树、红黑树、哈夫曼树、前缀树的理解
-
二叉搜索树:
- 定义:二叉搜索树是一种特殊的二叉树,对于树中的每个节点,其左子树中的所有节点的值都小于该节点的值,右子树中的所有节点的值都大于该节点的值。
- 特点:
- 中序遍历二叉搜索树可以得到一个有序的序列。
- 查找、插入和删除操作的时间复杂度在平均情况下为 O (log n),但在最坏情况下可能会退化为 O (n),当二叉搜索树退化为一条链时就会出现这种情况。
- 用途:常用于实现动态集合的数据结构,如集合的插入、删除、查找等操作。
以下是用 Go 语言实现一个简单的二叉搜索树:
package main
type BinarySearchTree struct {
root *TreeNode
}
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func (bst *BinarySearchTree) Insert(val int) {
bst.root = insert(bst.root, val)
}
func insert(node *TreeNode, val int) *TreeNode {
if node == nil {
return &TreeNode{Val: val}
}
if val < node.Val {
node.Left = insert(node.Left, val)
} else if val > node.Val {
node.Right = insert(node.Right, val)
}
return node
}
func (bst *BinarySearchTree) Search(val int) bool {
return search(bst.root, val)
}
func search(node *TreeNode, val int) bool {
if node == nil {
return false
}
if val == node.Val {
return true
} else if val < node.Val {
return search(node.Left, val)
} else {
return search(node.Right, val)
}
}
平衡二叉树(AVL 树):
定义:平衡二叉树是一种特殊的二叉树,它的左右子树的高度差不超过 1。
特点:
- 保持树的平衡可以确保查找、插入和删除操作的时间复杂度始终保持在 O (log n)。
- 通过旋转操作(左旋、右旋)来维持平衡。
用途:在需要高效进行查找、插入和删除操作,并且数据量较大的情况下使用。
以下是用 Go 语言实现的 AVL 树代码:
package main
type AVLTreeNode struct {
Val int
Left *AVLTreeNode
Right *AVLTreeNode
Height int
}
func NewAVLTreeNode(val int) *AVLTreeNode {
return &AVLTreeNode{Val: val, Height: 1}
}
func height(node *AVLTreeNode) int {
if node == nil {
return 0
}
return node.Height
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func getBalance(node *AVLTreeNode) int {
if node == nil {
return 0
}
return height(node.Left) - height(node.Right)
}
func rightRotate(y *AVLTreeNode) *AVLTreeNode {
x := y.Left
T2 := x.Right
x.Right = y
y.Left = T2
y.Height = max(height(y.Left), height(y.Right)) + 1
x.Height = max(height(x.Left), height(x.Right)) + 1
return x
}
func leftRotate(x *AVLTreeNode) *AVLTreeNode {
y := x.Right
T2 := y.Left
y.Left = x
x.Right = T2
x.Height = max(height(x.Left), height(x.Right)) + 1
y.Height = max(height(y.Left), height(y.Right)) + 1
return y
}
func insert(node *AVLTreeNode, val int) *AVLTreeNode {
if node == nil {
return NewAVLTreeNode(val)
}
if val < node.Val {
node.Left = insert(node.Left, val)
} else if val > node.Val {
node.Right = insert(node.Right, val)
} else {
return node
}
node.Height = max(height(node.Left), height(node.Right)) + 1
balance := getBalance(node)
if balance > 1 && val < node.Left.Val {
return rightRotate(node)
}
if balance < -1 && val > node.Right.Val {
return leftRotate(node)
}
if balance > 1 && val > node.Left.Val {
node.Left = leftRotate(node.Left)
return rightRotate(node)
}
if balance < -1 && val < node.Right.Val {
node.Right = rightRotate(node.Right)
return leftRotate(node)
}
return node
}
type AVLTree struct {
root *AVLTreeNode
}
func NewAVLTree() *AVLTree {
return &AVLTree{}
}
func (t *AVLTree) Insert(val int) {
t.root = insert(t.root, val)
}
红黑树:
定义:红黑树是一种自平衡的二叉搜索树,每个节点都带有颜色属性(红色或黑色),并满足一定的性质。
特点:
- 从根节点到叶子节点的最长路径不超过最短路径的两倍。
- 插入和删除操作可能会导致树的不平衡,但可以通过旋转和重新着色等操作来保持树的平衡。
用途:广泛应用于各种需要高效查找、插入和删除操作的场景,如 C++ 的 STL 中的关联容器、Java 的 TreeMap 和 TreeSet 等。
以下是用 Go 语言实现的红黑树代码:
package main
type Color bool
const (
Red Color = true
Black Color = false
)
type RBTreeNode struct {
Val int
Left *RBTreeNode
Right *RBTreeNode
Color Color
}
func NewRBTreeNode(val int) *RBTreeNode {
return &RBTreeNode{Val: val, Color: Red}
}
func isRed(node *RBTreeNode) bool {
if node == nil {
return false
}
return node.Color == Red
}
func rotateLeft(h *RBTreeNode) *RBTreeNode {
x := h.Right
h.Right = x.Left
x.Left = h
x.Color = h.Color
h.Color = Red
return x
}
func rotateRight(h *RBTreeNode) *RBTreeNode {
x := h.Left
h.Left = x.Right
x.Right = h
x.Color = h.Color
h.Color = Red
return x
}
func flipColors(h *RBTreeNode) {
h.Color = Red
h.Left.Color = Black
h.Right.Color = Black
}
func insert(root *RBTreeNode, val int) *RBTreeNode {
if root == nil {
return NewRBTreeNode(val)
}
if val < root.Val {
root.Left = insert(root.Left, val)
} else if val > root.Val {
root.Right = insert(root.Right, val)
} else {
return root
}
if isRed(root.Right) &&!isRed(root.Left) {
root = rotateLeft(root)
}
if isRed(root.Left) && isRed(root.Left.Left) {
root = rotateRight(root)
}
if isRed(root.Left) && isRed(root.Right) {
flipColors(root)
}
return root
}
type RBTree struct {
root *RBTreeNode
}
func NewRBTree() *RBTree {
return &RBTree{}
}
func (t *RBTree) Insert(val int) {
t.root = insert(t.root, val)
t.root.Color = Black
}
573

被折叠的 条评论
为什么被折叠?



