GO - 在递归函数中切换语句

时间:2014-03-11 11:04:51

标签: for-loop recursion go switch-statement

我有一个我试图实现的算法,但从技术角度来看,目前我完全不知道如何这样做。

我们有5片花车:

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

转换声明:

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语句
  3. 运行smallestFloat
  4. 如果smallestFloat达到默认情况,则从mySlice获取下一个最小的浮点数
  5. 再次执行第2步。
  6. 我已经成功完成了for循环和第2步的第一步,但我仍然坚持第3步和第4步。我现在还不知道我是怎么做的。可能会再次将mySlice中的下一个最小的浮动重新送到switch语句......

    我很感激能解决我的问题。

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

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

1 个答案:

答案 0 :(得分: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
    }
}