Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef CHRE_UTIL_HEAP_IMPL_H_
     18 #define CHRE_UTIL_HEAP_IMPL_H_
     19 
     20 #include <utility>
     21 
     22 #include "chre/platform/assert.h"
     23 #include "chre/util/dynamic_vector.h"
     24 #include "chre/util/fixed_size_vector.h"
     25 
     26 namespace chre {
     27 
     28 namespace {
     29 
     30 template<typename ContainerType, typename CompareFunction>
     31 void siftUp(ContainerType& container, size_t index,
     32             const CompareFunction& compare) {
     33   CHRE_ASSERT(index < container.size());
     34   size_t current = index;
     35   while (current > 0) {
     36     size_t parent = (current - 1) / 2;
     37     if (compare(container[parent], container[current])) {
     38       container.swap(parent, current);
     39       current = parent;
     40     } else {
     41       break;
     42     }
     43   }
     44 }
     45 
     46 template<typename ContainerType, typename CompareFunction>
     47 void siftDown(ContainerType& container, size_t index,
     48               const CompareFunction& compare) {
     49   CHRE_ASSERT(index < container.size());
     50   size_t current = index;
     51 
     52   // The last element is to be removed. If that's the element being indexed,
     53   // it's a no-op.
     54   while (index < container.size() - 1) {
     55     size_t child = 2 * current + 1;  // left child
     56 
     57     // If there are two children, pick the dominant one.
     58     if (child + 1 < container.size() - 1 &&
     59         compare(container[child], container[child + 1])) {
     60       child++;
     61     }
     62 
     63     // If the current element is not childless and the dominant child dominates
     64     // over it, swap and continue.
     65     if (child < container.size() - 1 &&
     66         compare(container[current], container[child])) {
     67       container.swap(current, child);
     68       current = child;
     69     } else {
     70       break;
     71     }
     72   }
     73 }
     74 
     75 }  // namespace
     76 
     77 template<typename ContainerType, typename CompareFunction>
     78 void push_heap(ContainerType& container, const CompareFunction& compare) {
     79   CHRE_ASSERT(container.size() > 0);
     80   if (container.size() > 0) {
     81     siftUp(container, container.size() - 1, compare);
     82   }
     83 }
     84 
     85 template<typename ContainerType, typename CompareFunction>
     86 void pop_heap(ContainerType& container, const CompareFunction& compare) {
     87   CHRE_ASSERT(container.size() > 0);
     88   if (container.size() > 0) {
     89     container.swap(0, container.size() - 1);
     90     siftDown(container, 0, compare);
     91   }
     92 }
     93 
     94 template<typename ContainerType, typename CompareFunction>
     95 void remove_heap(ContainerType& container, size_t index,
     96                  const CompareFunction& compare) {
     97   CHRE_ASSERT(index < container.size());
     98   container.swap(index, container.size() - 1);
     99 
    100   size_t parent = (index - 1) / 2;
    101   // When index = 0, it has no parent and can only sift down.
    102   if (index > 0 && compare(container[parent], container[index])) {
    103     siftUp(container, index, compare);
    104   } else {
    105     siftDown(container, index, compare);
    106   }
    107 }
    108 
    109 }  // namespace chre
    110 
    111 #endif  // CHRE_UTIL_PRIORITY_QUEUE_IMPL_H_
    112