source: branches/kendall-score/yat/utility/ranking/Impl.cc @ 4071

Last change on this file since 4071 was 4071, checked in by Peter, 19 months ago

Add variables height_ and size_ in NodeBase?, which describes the longest distance to its leaves and the size of the subtree in which it is the root, respectively. Use these variables to calculate the ranking, which means the ranking now scales like the height rather than the number of nodes. refs #710

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 3.8 KB
Line 
1// $Id: Impl.cc 4071 2021-08-18 02:31:29Z peter $
2
3/*
4  Copyright (C) 2021 Peter Johansson
5
6  This file is part of the yat library, http://dev.thep.lu.se/yat
7
8  The yat library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 3 of the
11  License, or (at your option) any later version.
12
13  The yat library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with yat. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include <config.h>
23
24#include "Ranking.h"
25
26#include <cassert>
27#include <cstddef>
28#include <iostream>
29
30namespace theplu {
31namespace yat {
32namespace utility {
33namespace ranking {
34
35  Impl::Impl(void)
36  {
37    reset();
38  }
39
40
41  Impl::Impl(Impl&& from)
42  {
43    reset();
44    if (from.head_.parent_)
45      move_data(std::move(from));
46  }
47
48
49  Impl& Impl::operator=(Impl&& rhs)
50  {
51    assert(!head_.parent_);
52    move_data(std::move(rhs));
53    assert(validate());
54    return *this;
55  }
56
57
58  void Impl::move_data(Impl&& from)
59  {
60    assert(head_.parent_ == nullptr);
61    head_.parent_ = from.head_.parent_;
62    head_.left_ = from.head_.left_;
63    assert(head_.right_ == &head_);
64    head_.parent_->right_ = &head_;
65    head_.height_ = from.head_.height_;
66    head_.size_ = from.head_.size_;
67    from.reset();
68    assert(validate());
69  }
70
71
72  void Impl::relink(const NodeBase* node, NodeBase* child)
73  {
74    assert(node->parent_);
75    assert(node != &head_);
76    assert(child != &head_);
77
78    // make child the child of node's parent
79    if (node->is_left_node())
80      node->parent_->left_ = child;
81    else if (node->is_right_node())
82      node->parent_->right_ = child;
83
84    // make node's parent the parent of child
85    if (child)
86      child->parent_ = node->parent_;
87
88    // inherit the kids
89    if (child) {
90      if (node->left_ && node->left_!=child) {
91        assert(!child->left_);
92        child->left_ = node->left_;
93        if (node->left_)
94          node->left_->parent_ = child;
95      }
96      if (node->right_ && node->right_!=child) {
97        assert(!child->right_);
98        child->right_ = node->right_;
99        if (node->right_)
100          node->right_->parent_ = child;
101      }
102    }
103
104    // update pointer to left_most node
105    if (head_.left_ == node) {
106      head_.left_ = child ? child : node->parent_;
107    }
108    assert(child==nullptr || child->is_left_node() || child->is_right_node());
109  }
110
111
112  size_t Impl::ranking(const NodeBase* node) const
113  {
114    if (node->is_head_node())
115      return size(node->parent_);
116
117    // root node
118    if (node->parent_ == nullptr)
119      return size(node->left_);
120
121    // The rank of the parent is the sum of the rank of the
122    // left->child, the child itself, and the size of the child's
123    // right branch.
124    if (node->is_left_node())
125      return ranking(node->parent_) - (1 + size(node->right_));
126
127    // right node
128    return ranking(node->parent_) + 1 + size(node->left_);
129  }
130
131
132  void Impl::reset(void)
133  {
134    // FIXME do we need to destruct parent and rest of tree?
135    head_.parent_ = nullptr;
136    head_.left_ = &head_;
137    head_.right_ = &head_;
138    // we don't count the head node
139    head_.height_ = 0;
140    head_.size_ = 0;
141    assert(validate());
142  }
143
144
145  bool Impl::validate(void) const
146  {
147    if (head_.parent_ == nullptr) {
148      assert(head_.left_ == &head_);
149      assert(head_.right_ == &head_);
150      assert(head_.is_head_node());
151    }
152    else {
153      assert(head_.parent_);
154      assert(head_.left_);
155      if (head_.parent_->right_ != &head_) {
156        return false;
157      }
158    }
159
160    if (head_.parent_) {
161      if (head_.parent_->left_most() != head_.left_) {
162        std::cerr << "head_.left incorrect\n";
163        return false;
164      }
165      if (!head_.parent_->recursive_validate())
166        return false;
167    }
168    else if (!head_.validate())
169      return false;
170
171    return true;
172  }
173
174}
175}}} // of namespace utility, yat, and theplu
Note: See TracBrowser for help on using the repository browser.