Branch data Line data Source code
1 : : /* 2 : : * This file is part of the MicroPython project, http://micropython.org/ 3 : : * 4 : : * The MIT License (MIT) 5 : : * 6 : : * Copyright (c) 2020 Damien P. George 7 : : * 8 : : * Permission is hereby granted, free of charge, to any person obtaining a copy 9 : : * of this software and associated documentation files (the "Software"), to deal 10 : : * in the Software without restriction, including without limitation the rights 11 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 : : * copies of the Software, and to permit persons to whom the Software is 13 : : * furnished to do so, subject to the following conditions: 14 : : * 15 : : * The above copyright notice and this permission notice shall be included in 16 : : * all copies or substantial portions of the Software. 17 : : * 18 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 : : * THE SOFTWARE. 25 : : */ 26 : : #ifndef MICROPY_INCLUDED_PY_PAIRHEAP_H 27 : : #define MICROPY_INCLUDED_PY_PAIRHEAP_H 28 : : 29 : : // This is an implementation of a pairing heap. It is stable and has deletion 30 : : // support. Only the less-than operation needs to be defined on elements. 31 : : // 32 : : // See original paper for details: 33 : : // Michael L. Fredman, Robert Sedjewick, Daniel D. Sleator, and Robert E. Tarjan. 34 : : // The Pairing Heap: A New Form of Self-Adjusting Heap. 35 : : // Algorithmica 1:111-129, 1986. 36 : : // https://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdf 37 : : 38 : : #include <assert.h> 39 : : #include "py/obj.h" 40 : : 41 : : // This struct forms the nodes of the heap and is intended to be extended, by 42 : : // placing it first in another struct, to include additional information for the 43 : : // element stored in the heap. It includes "base" so it can be a MicroPython 44 : : // object allocated on the heap and the GC can automatically trace all nodes by 45 : : // following the tree structure. 46 : : typedef struct _mp_pairheap_t { 47 : : mp_obj_base_t base; 48 : : struct _mp_pairheap_t *child; 49 : : struct _mp_pairheap_t *child_last; 50 : : struct _mp_pairheap_t *next; 51 : : } mp_pairheap_t; 52 : : 53 : : // This is the function for the less-than operation on nodes/elements. 54 : : typedef int (*mp_pairheap_lt_t)(mp_pairheap_t *, mp_pairheap_t *); 55 : : 56 : : // Core functions. 57 : : mp_pairheap_t *mp_pairheap_meld(mp_pairheap_lt_t lt, mp_pairheap_t *heap1, mp_pairheap_t *heap2); 58 : : mp_pairheap_t *mp_pairheap_pairing(mp_pairheap_lt_t lt, mp_pairheap_t *child); 59 : : mp_pairheap_t *mp_pairheap_delete(mp_pairheap_lt_t lt, mp_pairheap_t *heap, mp_pairheap_t *node); 60 : : 61 : : // Create a new heap. 62 : : static inline mp_pairheap_t *mp_pairheap_new(mp_pairheap_lt_t lt) { 63 : : (void)lt; 64 : : return NULL; 65 : : } 66 : : 67 : : // Initialise a single pairing-heap node so it is ready to push on to a heap. 68 : 556 : static inline void mp_pairheap_init_node(mp_pairheap_lt_t lt, mp_pairheap_t *node) { 69 : 556 : (void)lt; 70 : 556 : node->child = NULL; 71 [ + - ]: 556 : node->next = NULL; 72 : : } 73 : : 74 : : // Test if the heap is empty. 75 : : static inline bool mp_pairheap_is_empty(mp_pairheap_lt_t lt, mp_pairheap_t *heap) { 76 : : (void)lt; 77 : : return heap == NULL; 78 : : } 79 : : 80 : : // Peek at the top of the heap. Will return NULL if empty. 81 : : static inline mp_pairheap_t *mp_pairheap_peek(mp_pairheap_lt_t lt, mp_pairheap_t *heap) { 82 : : (void)lt; 83 : : return heap; 84 : : } 85 : : 86 : : // Push new node onto existing heap. Returns the new heap. 87 : 319484 : static inline mp_pairheap_t *mp_pairheap_push(mp_pairheap_lt_t lt, mp_pairheap_t *heap, mp_pairheap_t *node) { 88 [ + - - + ]: 319484 : assert(node->child == NULL && node->next == NULL); 89 : 319484 : return mp_pairheap_meld(lt, node, heap); // node is first to be stable 90 : : } 91 : : 92 : : // Pop the top off the heap, which must not be empty. Returns the new heap. 93 : 319364 : static inline mp_pairheap_t *mp_pairheap_pop(mp_pairheap_lt_t lt, mp_pairheap_t *heap) { 94 [ - + ]: 319364 : assert(heap->next == NULL); 95 : 319364 : mp_pairheap_t *child = heap->child; 96 : 319364 : heap->child = NULL; 97 : 319364 : return mp_pairheap_pairing(lt, child); 98 : : } 99 : : 100 : : #endif // MICROPY_INCLUDED_PY_PAIRHEAP_H