github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/algorithm/datastructures/minheap/heap_test.go (about)

     1  package minheap
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"strconv"
     7  	"testing"
     8  	"time"
     9  )
    10  
    11  type Task struct {
    12  	Name     string
    13  	Priority int
    14  }
    15  
    16  func taskCompare(v1, v2 interface{}) int {
    17  	t1, _ := v1.(*Task)
    18  	t2, _ := v2.(*Task)
    19  	return t1.Priority - t2.Priority
    20  }
    21  
    22  func eqTaskFunc(e, b interface{}) bool {
    23  	t1, ok1 := e.(*Task)
    24  	t2, ok2 := b.(*Task)
    25  	if ok1 && ok2 && t1 == t2 {
    26  		fmt.Println("删除了 ", t1.Name)
    27  		return true
    28  	}
    29  	return false
    30  }
    31  
    32  func generatorTask() []interface{} {
    33  	rand.Seed(time.Now().Unix())
    34  	const size = 10
    35  	d := make([]interface{}, 0, size)
    36  	for i := 0; i < size; i++ {
    37  		p := rand.Intn(300)
    38  		d = append(d, &Task{
    39  			Name:     "task-" + strconv.Itoa(i),
    40  			Priority: p,
    41  		})
    42  	}
    43  	return d
    44  }
    45  
    46  func TestHeap_Remove(t *testing.T) {
    47  	tasks := generatorTask()
    48  	for i := 0; i < len(tasks); i++ {
    49  		fmt.Println(tasks[i])
    50  	}
    51  	fmt.Println("----------------")
    52  	h := NewHeap(taskCompare)
    53  	h.Heapify(tasks...)
    54  	remove := h.Remove(tasks[1], eqTaskFunc)
    55  
    56  	fmt.Println("删除 ", remove)
    57  	for h.Len() != 0 {
    58  		e := h.Poll()
    59  		if t, ok := e.(*Task); ok {
    60  			fmt.Println(t)
    61  		}
    62  	}
    63  }
    64  
    65  func TestHeap_Add(t *testing.T) {
    66  	h := NewHeap(taskCompare)
    67  	h.Heapify(generatorTask()...)
    68  	cnt := 0
    69  	for h.Len() != 0 {
    70  		cnt++
    71  		pe := h.Peek().(*Task)
    72  		pe.Name = pe.Name + "_p" + strconv.Itoa(cnt)
    73  		e := h.Poll()
    74  		if t, ok := e.(*Task); ok {
    75  			fmt.Println(t)
    76  		}
    77  	}
    78  }
    79  
    80  func Test_topKFrequent(t *testing.T) {
    81  	ret := topKFrequent([]int{1, 1, 1, 2, 2, 3}, 2)
    82  	t.Log(ret)
    83  }
    84  
    85  // 通过heap 求中位数 , 百分位等问题
    86  // 思路: 维护两个堆, 一个最大堆(保存前半部数据),一个最小堆(保存后半部分)
    87  // 动态维护: 1 比较插入值的大小,小于大堆top进大堆, 大于小堆top进小堆, 在大堆小堆之间得范围随便插入到哪
    88  // 		   2 维护两堆的数量平衡, 通过堆之间的数据搬迁,使得两个堆的size比例满足中位数 或 百分位的比例
    89  
    90  // 347. Top K Frequent Elements
    91  // https://leetcode.com/problems/top-k-frequent-elements/description/
    92  func topKFrequent(nums []int, k int) []int {
    93  
    94  	// 统计
    95  	freqMap := make(map[int]int)
    96  	for _, v := range nums {
    97  		if _, ok := freqMap[v]; ok {
    98  			freqMap[v]++
    99  		} else {
   100  			freqMap[v] = 1
   101  		}
   102  	}
   103  	var fdd []numFrequent
   104  	for k, v := range freqMap {
   105  		fdd = append(fdd, numFrequent{num: k, freq: v})
   106  	}
   107  
   108  	h := NewHeap(func(v1, v2 interface{}) int {
   109  		i1 := v1.(numFrequent)
   110  		i2 := v2.(numFrequent)
   111  		if i1.freq > i2.freq {
   112  			return 1
   113  		} else if i1.freq < i2.freq {
   114  			return -1
   115  		} else {
   116  			return 0
   117  		}
   118  	})
   119  	for _, v := range fdd {
   120  		if h.Len() < k {
   121  			h.Add(v)
   122  		} else if h.Peek().(numFrequent).freq < v.freq {
   123  			h.Poll()
   124  			h.Add(v)
   125  		}
   126  	}
   127  	var ret []int
   128  	for h.Peek() != nil {
   129  		ret = append(ret, h.Poll().(numFrequent).num)
   130  	}
   131  	return ret
   132  }
   133  
   134  type numFrequent struct {
   135  	num  int
   136  	freq int
   137  }