满二叉树: 所有的层节点数都是该层所能容纳节点的最⼤数量(满足
2
n
2^n
2n;
n
>
=
0
n > =0
n>=0) ;
完全二叉树: 若⼆叉树的深度为 h ,除了 h 层外,其他层的节点数都是该层所能容纳节点的最⼤数量(满⾜ ),且 h 层都集中在最左侧;
最小堆:
- 是一颗完全二叉树;
- 某一个节点的值总是小于等于它的子节点的值;
- 堆中每个节点的子树都是最小堆;
为了满⾜完全⼆叉树定义,往⼆叉树最⾼层沿着最左侧添加⼀个节点;然后考虑是否能上升操作;如果此时添加值为 4 的节点, 4 节点是5节点的左⼦树; 4 ⽐ 5 ⼩, 4 和 5 需要交换位置;
删除操作删除操作需要先查找是否包含这个节点,最⼩堆的查找效率是
O
(
n
)
O(n)
O(n); 查找之后,交换最后一个节点,先考虑下降操作,如果操作失败则上升操作; 最后删除最后一个节点;
例如:假设删除 1 号节点,则需要下沉操作;假设删除 9 号节点,则需要上升操作;
//minheap.h #pragma once #include#include
//minheap.cpp #include#include #include #include "minheap.h" #include static uint32_t current_time() { //获取当前时间 uint32_t t; struct timespec ti; clock_gettime(CLOCK_MONOTONIC, &ti); t = (uint32_t)ti.tv_sec * 1000; t += ti.tv_nsec / 1000000; return t; } int MinHeapTimer::AddTimer(uint32_t expire, TimerHandler cb) { //添加定时器 和callback函数 int64_t timeout = current_time() + expire; TimerNode *node = new TimerNode; int id = Count(); //添加一个node id就+1 node->id = id; node->expire = timeout; node->cb = cb; node->idx = (int)_heap.size(); //元素在heap的位置 _heap.push_back(node); _shiftUp((int)(_heap.size() - 1)); //因为插入元素是放在最后一个位置上,所以要进行上升处理 _map.insert(make_pair(id, node)); //同时map进行记录 return id; } bool MinHeapTimer::DelTimer(int id) { //删除一个定时器操作 auto iter = _map.find(id); if(iter == _map.end()) return false; _delNode(iter->second); //查找到之后删除node return true; } void MinHeapTimer::_delNode(TimerNode *node) { //删除一个节点 int last = (int)_heap.size() - 1; // 删除节点的时候需要和堆中的最后一个节点进行交换 int idx = node->idx; if(idx != last) { std::swap(_heap[idx], _heap[last]); _heap[idx]->idx = idx; if(!_shiftDown(idx)) //交换完 先进行下沉操作, 下沉失败 在上升处理 _shiftUp(idx); } _heap.pop_back(); _map.erase(node->id); delete node; } void MinHeapTimer::ExpireTimer() { if (_heap.empty()) return; uint32_t now = current_time(); do{ TimerNode* node = _heap.front(); if( now < node->expire) break; for(int i =0; i < _heap.size(); i++) { //遍历哪个节点是否到期 std::cout << "touch.....idx: " << _heap[i]->idx << " id: " << _heap[i]->id << " expire: " << _heap[i]->expire << std::endl; } if(node->cb) node->cb(node); _delNode(node); }while(!_heap.empty()); } bool MinHeapTimer::_shiftDown(int pos) { //下沉操作 int last = (int)_heap.size() - 1; int idx = pos; for(;;) { int left = 2 * idx + 1; //左儿子的pos if((left >= last) || (left < 0)) break; int min = left; int right = left + 1; //右儿子 if(right < last && !_lessThan(left, right)){ //查询左右两个儿子的最小值 min = right; } if(!_lessThan(min, idx)) //如果idx就是最小的,则不需要交换 break; std::swap(_heap[idx], _heap[min]); _heap[idx]->idx = idx; _heap[min]->idx = min; idx = min; } return idx > pos; } void MinHeapTimer::_shiftUp(int pos) //上升操作 和下沉同理 { for (;;) { int parent = (pos - 1) / 2; // parent node if (parent == pos || !_lessThan(pos, parent)) { break; } std::swap(_heap[parent], _heap[pos]); _heap[parent]->idx = parent; _heap[pos]->idx = pos; pos = parent; } } void print_hello(TimerNode *te) { std::cout << "hello world time = " << te->idx << "t" << te->id << std::endl; } int main() { MinHeapTimer mht; mht.AddTimer(0, print_hello); mht.AddTimer(1000, print_hello); mht.AddTimer(7000, print_hello); mht.AddTimer(2000, print_hello); mht.AddTimer(9000, print_hello); mht.AddTimer(10000, print_hello); mht.AddTimer(6000, print_hello); mht.AddTimer(3000, print_hello); for (;;) { mht.ExpireTimer(); usleep(10000); } return 0; }



