【问题标题】:GO - switch statement in a recursive functionGO - 递归函数中的 switch 语句
【发布时间】:2014-03-11 11:04:51
【问题描述】:

我有一个正在尝试实现的算法,但从技术角度来看,目前我完全不知道该怎么做。

我们有 5 个浮点数的切片:

mySlice := [float1, float2, float3, float4, float5]

还有一个switch语句:

aFloat := mySlice[index]

switch aFloat {
  case 1:
    {
       //do something 
    }
  case 2:
    {
       //do something 
    }
  case 3:
    {
       //do something 
    }
  case 4:
    {
       //do something 
    }
  case 5:
    {
       //do something 
    }
  default:
    {
       //somehow go back to slice, take the next smallest and run
       //through the switch statement again
    }
}

我想做的如下:

  1. 确定 mySlice 的最小元素 ex:smallestFloat
  2. 通过switch语句运行smallestFloat
  3. 如果smallestFloat 进入默认情况,则从 mySlice 中获取下一个最小的浮点数
  4. 再次执行第 2 步。

我已经设法用 for 循环和第 2 步完成了第一步,但我被困在第 3 步和第 4 步。我目前不知道如何进行重新喂食再次从 mySlice 到 switch 语句的下一个最小浮点数...

如果我能解决我的问题,我将不胜感激。

编辑:我认为将我的解决方案应用于上述算法会很好。

  1. 创建另一个切片,它将是 mySlice 的排序版本
  2. 创建一个 map[int]value,其中索引将对应于该值在未排序切片中的位置,但映射的项目将按照与排序切片相同的顺序插入。

结果:一个值排序的映射,其索引对应于原始未排序切片的位置

【问题讨论】:

  • 地图不是有序结构。并且不能保证在同一个映射的不同迭代之间键的顺序相同。
  • 感谢您的提示。我会留意的

标签: for-loop recursion go switch-statement


【解决方案1】:

这是一个使用最小优先级队列的实现。浮点数的原始输入切片未更改。可以在Go playground上运行

注意:在处理递归函数时,你需要对堆栈溢出感到厌烦。 Go 仅在有限的情况下进行尾递归优化。有关这方面的更多信息, 参考this answer

这个特定的例子甚至比摊销的 O(log N) 时间更好,因为它不必在中途调整优先级队列的大小。这保证了 O(log N)。

package main

import (
    "fmt"
)

func main() {
    slice := []float64{2, 1, 13, 4, 22, 0, 5, 7, 3}
    fmt.Printf("Order before: %v\n", slice)

    queue := NewMinPQ(slice)

    for !queue.Empty() {
        doSmallest(queue)
    }

    fmt.Printf("Order after: %v\n", slice)
}

func doSmallest(queue *MinPQ) {
    if queue.Empty() {
        return
    }

    v := queue.Dequeue()

    switch v {
    case 1:
        fmt.Println("Do", v)
    case 2:
        fmt.Println("Do", v)
    case 3:
        fmt.Println("Do", v)
    case 4:
        fmt.Println("Do", v)
    case 5:
        fmt.Println("Do", v)
    default:
        // No hit, do it all again with the next value.
        doSmallest(queue)
    }
}

// MinPQ represents a Minimum priority queue.
// It is implemented as a binary heap.
//
// Values which are enqueued can be dequeued, but will be done
// in the order where the smallest item is returned first.
type MinPQ struct {
    values  []float64 // Original input list -- Order is never changed.
    indices []int     // List of indices into values slice.
    index   int       // Current size of indices list.
}

// NewMinPQ creates a new MinPQ heap for the given input set.
func NewMinPQ(set []float64) *MinPQ {
    m := new(MinPQ)
    m.values = set
    m.indices = make([]int, 1, len(set))

    // Initialize the priority queue.
    // Use the set's indices as values, instead of the floats
    // themselves. As these may not be re-ordered.
    for i := range set {
        m.indices = append(m.indices, i)
        m.index++
        m.swim(m.index)
    }

    return m
}

// Empty returns true if the heap is empty.
func (m *MinPQ) Empty() bool { return m.index == 0 }

// Dequeue removes the smallest item and returns it.
// Returns nil if the heap is empty.
func (m *MinPQ) Dequeue() float64 {
    if m.Empty() {
        return 0
    }

    min := m.indices[1]

    m.indices[1], m.indices[m.index] = m.indices[m.index], m.indices[1]
    m.index--
    m.sink(1)
    m.indices = m.indices[:m.index+1]
    return m.values[min]
}

// greater returns true if element x is greater than element y.
func (m *MinPQ) greater(x, y int) bool {
    return m.values[m.indices[x]] > m.values[m.indices[y]]
}

// sink reorders the tree downwards.
func (m *MinPQ) sink(k int) {
    for 2*k <= m.index {
        j := 2 * k

        if j < m.index && m.greater(j, j+1) {
            j++
        }

        if m.greater(j, k) {
            break
        }

        m.indices[k], m.indices[j] = m.indices[j], m.indices[k]
        k = j
    }
}

// swim reorders the tree upwards.
func (m *MinPQ) swim(k int) {
    for k > 1 && m.greater(k/2, k) {
        m.indices[k], m.indices[k/2] = m.indices[k/2], m.indices[k]
        k /= 2
    }
}

【讨论】:

  • 我已经应用了这个方法,但这不是我需要的。我需要切片的每个元素保持在其原始位置。正如我的算法中提到的,我需要identify 最小并检索值,而不是修改元素的索引。
  • 在这种情况下,我会查看我在答案中提到的优先级队列。它可以使用列表索引作为值来构造。这样,您的切片可以保持原样,但您仍然可以在摊销 O(log n) 时间内找到最小的浮点数。而每次只循环切片是 O(N) 时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-24
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多