【分享】 使用堆作爲底層數據結構來優化”紅包分配算法“

    我之前的博客中用c語言寫了一個紅包均分算法,用到的數據結構是鏈式數組,今日用堆改進此算法-相較穩定的紅包算法實現/c語言實現,使用的語言是Go語言。

   核心算法相同(不瞭解的同學可以點擊上面鏈接閱讀),所以直接上代碼:

//使用堆完成紅包分配算法
package main

import "fmt"

//用於影響分配結果的因子
var yz float32 = 0

type rbHeap struct {
    count int
    amount float32
    heap []float32
}

//值分割算法
func fp(value float32) (va, vb float32) {
    yz += 1.0
    va, vb = value-yz, yz
    return
}

func rbHeapDown(heap []float32, ni int) {
    if len(heap) <= 1 {
        return
    }
    hl := len(heap)-1
    for {
        nl := ni*2+1
        nr := ni*2+2
        if nl <= hl && nr <= hl{
            //與左節點比較, 如果左右節點相等的情況, 左子節點優先進行
            if heap[nl]>=heap[nr] && heap[ni]<heap[nl] {
                heap[nl], heap[ni] = heap[ni], heap[nl]
                ni = nl
                continue
                //與右節點比較
            } else if heap[ni]<heap[nr] {
                heap[nr], heap[ni] = heap[ni], heap[nr]
                ni = nr
                continue
            }
        } else if nl<=hl && heap[ni]<heap[nl] {
            //同末尾節點比較
            heap[nl], heap[ni] = heap[ni], heap[nl]
        }
        break
    }
}

func rbHeapUp(heap []float32, ni int) {
    if ni <= 0 {
        return
    }
    for ; ni >= 1; {
        pi := (ni-1)/2
        if heap[ni] > heap[pi] {
            heap[ni], heap[pi] = heap[pi], heap[ni]
            ni = pi
            continue
        }
        break
    }
}



func (rh *rbHeap) heapPush(value float32, root bool) {
    if root {
        rh.heap[0] = value
        rbHeapDown(rh.heap, 0)
    } else {
        rh.heap = append(rh.heap, value)
        rbHeapUp(rh.heap, len(rh.heap)-1)
    }
}

func (rh *rbHeap) heapPop() (float32, error) {
    if rh.heap != nil && len(rh.heap) > 0 {
        return rh.heap[0], nil
    }
    return 0.0, fmt.Errorf("heap is empty")
}

func processHeap(amount float32, count int) []float32 {
    rh := &rbHeap{
        count: count,
        amount: amount,
        heap: make([]float32, 0, count),
    }
    va, vb := fp(amount)
    if va > vb {
        rh.heap = append(rh.heap, va)
        rh.heap = append(rh.heap, vb)
    } else {
        rh.heap = append(rh.heap, vb)
        rh.heap = append(rh.heap, va)
    }
    for i := 0; i < count-2; i++ {
        v, err := rh.heapPop()
        if err != nil {
            fmt.Printf("pop error:`%s`\n", err)
            break
        }
        va, vb := fp(v)
        rh.heapPush(va, true)
        rh.heapPush(vb, false)
    }
    return rh.heap
}

func main() {
    s := time.Now()
    result := processHeap(10000000000, 1000000)
    _ = result
    fmt.Println(time.Since(s).Milliseconds())
}

 

經過測試,該算法分配100w個紅包的耗時爲ms級別。(大概是因爲分配算法過於簡單吧)

發佈了34 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章