How to convert recursive tree search function to nonrecursively? - c++

I'm trying to explore the binary tree.
However, I have to implement recursive functions nonrecursively.
I've searched several ways to convert recursion to nonrecursive.
But it doesn't seem to apply to my code.
I wonder if I can convert my code to non-recursive and how I can convert it.
This is my code(recursive function)
const NODE* getNN(const float pos[DIM], const NODE* cur, int depth) {
if (!cur) return nullptr;
bool flag = pos[depth % DIM] < cur->pos[depth % DIM];
NODE* next{ flag ? cur->left : cur->right };
NODE* other{ flag ? cur->right : cur->left };
const NODE* temp = getNN(pos, next, depth + 1);
const NODE* best{ closest(pos, temp, cur) };
float r = this->distance(pos, best->pos);
float dr = pos[depth % DIM] - cur->pos[depth % DIM];
if (r >= dr * dr) {
temp = getNN(pos, other, depth + 1);
best = closest(pos, temp, best);
}
return best;
}
Here is what I expected
const NODE* getNN_NonRecur(const float pos[DIM])

It's been resolved it. Thank you for advice.
const NODE* getNN_NR(const float pos[DIM])
{
std::stack<std::pair<std::pair<NODE*, NODE*>, unsigned int>> st;
composeStack(st, pos, this->root, 0);
const NODE* best{ st.top().first.first };
while (!st.empty())
{
auto e = st.top(); st.pop();
if (!e.first.first) continue;
best = closest(pos, best, e.first.first);
float r = distance(pos, best->pos);
float dr = pos[e.second % DIM] - e.first.first->pos[e.second % DIM];
if (r >= dr * dr) {
composeStack(st, pos, e.first.second, e.second);
best = closest(pos, st.top().first.first, best);
}
}
return best;
}
void composeStack(std::stack<std::pair<std::pair<NODE*, NODE*>, unsigned int>>& st,
const float pos[DIM],
NODE* node, unsigned int depth)
{
NODE* cur = node;
st.push({ {node, nullptr}, depth });
while (cur) {
auto e = st.top();
cur = e.first.first; depth = e.second;
bool flag = pos[depth % DIM] < cur->pos[depth % DIM];
NODE* next{ flag ? cur->left : cur->right };
NODE* other{ flag ? cur->right : cur->left };
st.push(std::pair<std::pair
<NODE*, NODE*>, unsigned int>({ next, other }, depth + 1));
cur = next;
}
}

Related

Is there a better way to do a self-reference pointer in the base class that also works in derived classes?

I am writing some code on Splay Tree nodes. Without being too technical, I want to implement one base tree and one derived tree that supports reversion of the left and right sub-trees. The current excerpt looks like this:
struct node {
node *f, *c[2];
int size;
void push_down() {}
};
struct reversable_node : node {
int r;
void push_down() {
if (r) {
std::swap(c[0], c[1]);
c[0]->r ^= 1, c[1]->r ^= 1, r = 0;
}
}
};
This obviously does not work, because c[0] are of type node and does not have member r. Still, I know that c[0] of node only points to node and c[0] of reversable_node only points to reversable_node. So I can do some cast:
((reversable_node *)c[0])->r ^= 1, ((reversable_node *)c[1])->r ^= 1, r = 0;
But this looks super clumsy. Is there a better way to do a self-reference pointer in the base class that also works in derived classes?
P.S. The whole code looks like this:
struct node {
node *f, *c[2];
int size;
node() {
f = c[0] = c[1] = nullptr;
size = 1;
}
void push_down() {}
void update() {
size = 1;
for (int t = 0; t < 2; ++t)
if (c[t]) size += c[t]->size;
}
};
struct reversable_node : node {
int r;
reversable_node() : node() { r = 0; }
void push_down() {
if (r) {
std::swap(c[0], c[1]);
((reversable_node *)c[0])->r ^= 1, ((reversable_node *)c[1])->r ^= 1, r = 0;
}
}
};
template <typename T = node, int MAXSIZE = 500000>
struct tree {
T pool[MAXSIZE + 2];
node *root;
int size;
tree() {
size = 2;
root = pool[0], root->c[1] = pool[1], root->size = 2;
pool[1]->f = root;
}
void rotate(T *n) {
int v = n->f->c[0] == n;
node *p = n->f, *m = n->c[v];
p->push_down(), n->push_down();
n->c[v] = p, p->f = n, p->c[v ^ 1] = m;
if (m) m->f = p;
p->update(), n->update();
}
void splay(T *n, T *s = nullptr) {
while (n->f != s) {
T *m = n->f, *l = m->f;
if (l == s)
rotate(n);
else if ((l->c[0] == m) == (m->c[0] == n))
rotate(m), rotate(n);
else
rotate(n), rotate(n);
}
if (!s) root = n;
}
node *new_node() { return pool[size++]; }
void walk(node *n, int &v, int &pos) {
n->push_down();
int s = n->c[0] ? n->c[0]->size : 0;
(v = s > pos) && (pos -= s + 1);
}
void add_node(node *n, int pos) {
node *c = root;
int v;
++pos;
do {
walk(c, v, pos);
} while (c->c[v] && (c = c->c[v]));
c->c[v] = n, n->f = cur, splay(n);
}
node *find(int pos, int splay = true) {
node *c = root;
int v;
++pos;
do {
walk(c, v, pos);
} while (pos && (c = c->c[v]));
if (splay) splay(c);
return c;
}
node *find_range(int posl, int posr) {
node *l = find(posl - 1), *r = find(posr, false);
splay(r, l);
if (r->c[0]) r->c[0]->push_down();
return r->c[0];
}
};
So basically we have a flag of whether a node is reversed, and when we try to rotate the tree, we push down the flag from the node to its children. This may require some understanding of the Splay Tree.
P.S.2 It is supposed to be a library, but some use cases would be like this:
#include "../template.h"
splay::tree<splay::reversable_node> s;
void dfs(splay::reversable_node *n) {
if (n) {
// Push down the flag.
n->push_down();
dfs(n->c[0]);
// Do something about n...
dfs(n->c[1]);
}
}
int main() {
// Insert 5 nodes to the Splay Tree.
for (int i = 0; i < 5; ++i) s.add_node(s.new_node(), 0);
// Find a range of the tree.
splay::reversable_node *n = s.find_range(0, 3);
// Reverse it.
n->r = 1;
std::swap(n->c[0], n->c[1]);
// Traverse it in inorder.
dfs(s.root);
}
Anyway thanks to CRTP I got it to work.
namespace splay {
/**
* Abstract node struct.
*/
template <typename T>
struct node {
T *f, *c[2];
int size;
node() {
f = c[0] = c[1] = nullptr;
size = 1;
}
void push_down() {}
void update() {
size = 1;
for (int t = 0; t < 2; ++t)
if (c[t]) size += c[t]->size;
}
};
/**
* Abstract reversible node struct.
*/
template <typename T>
struct reversible_node : node<T> {
int r;
reversible_node() : node<T>() { r = 0; }
void push_down() {
node<T>::push_down();
if (r) {
for (int t = 0; t < 2; ++t)
if (node<T>::c[t]) node<T>::c[t]->reverse();
r = 0;
}
}
void update() { node<T>::update(); }
/**
* Reverse the range of this node.
*/
void reverse() {
std::swap(node<T>::c[0], node<T>::c[1]);
r = r ^ 1;
}
};
template <typename T, int MAXSIZE = 500000>
struct tree {
T pool[MAXSIZE + 2];
T *root;
int size;
tree() {
size = 2;
root = pool, root->c[1] = pool + 1, root->size = 2;
pool[1].f = root;
}
/**
* Helper function to rotate node.
*/
void rotate(T *n) {
int v = n->f->c[0] == n;
T *p = n->f, *m = n->c[v];
if (p->f) p->f->c[p->f->c[1] == p] = n;
n->f = p->f, n->c[v] = p;
p->f = n, p->c[v ^ 1] = m;
if (m) m->f = p;
p->update(), n->update();
}
/**
* Splay n so that it is under s (or to root if s is null).
*/
void splay(T *n, T *s = nullptr) {
while (n->f != s) {
T *m = n->f, *l = m->f;
if (l == s)
rotate(n);
else if ((l->c[0] == m) == (m->c[0] == n))
rotate(m), rotate(n);
else
rotate(n), rotate(n);
}
if (!s) root = n;
}
/**
* Get a new node from the pool.
*/
T *new_node() { return pool + size++; }
/**
* Helper function to walk down the tree.
*/
int walk(T *n, int &v, int &pos) {
n->push_down();
int s = n->c[0] ? n->c[0]->size : 0;
(v = s < pos) && (pos -= s + 1);
return s;
}
/**
* Insert node n to position pos.
*/
void insert(T *n, int pos) {
T *c = root;
int v;
++pos;
while (walk(c, v, pos), c->c[v] && (c = c->c[v]))
;
c->c[v] = n, n->f = c, splay(n);
}
/**
* Find the node at position pos. If sp is true, splay it.
*/
T *find(int pos, int sp = true) {
T *c = root;
int v;
++pos;
while ((pos < walk(c, v, pos) || v) && (c = c->c[v]))
;
if (sp) splay(c);
return c;
}
/**
* Find the range [posl, posr) on the splay tree.
*/
T *find_range(int posl, int posr) {
T *l = find(posl - 1), *r = find(posr, false);
splay(r, l);
if (r->c[0]) r->c[0]->push_down();
return r->c[0];
}
};
} // namespace splay
Some use case:
struct node : splay::reversible_node<node> {
int val;
void push_down() { splay::reversible_node<node>::push_down(); }
void update() { splay::reversible_node<node>::update(); }
};
splay::tree<node> t;
int N, M;
void inorder(node *n) {
static int f = 0;
if (!n) return;
n->push_down();
inorder(n->c[0]);
if (n->val) {
if (f) printf(" ");
f = 1;
printf("%d", n->val);
}
inorder(n->c[1]);
}
int main() {
scanf("%d%d", &N, &M);
for (int i = 0; i < N; ++i) {
node *n = t.new_node();
n->val = i + 1;
t.insert(n, i);
}
for (int i = 0, u, v; i < M; ++i) {
scanf("%d%d", &u, &v);
node *n = t.find_range(u - 1, v);
n->reverse();
}
inorder(t.root);
}
Hopefully this allows me to write Splay faster in CP.

strdup for converting const char* to char*

I have designed for Huffman tree convert binary code with shorter bin code. In main if you call a Binary tree.init(q), then the tree would come out with key: frequency and value: bin code. The problem is converting const char* with char*. I've looked at some codes, and here I converted it by using strdup. Sometimes works fine but sometimes doesn't work. so I checked out the parameter for the function. Is there wrong in calling strdup or maybe others?
#pragma once
#include <stdio.h>
#include <queue>
#include <iostream>
#include "pch.h"
#include <string.h>
#include <string>
#define _CRT_SECURE_NO_WARNINGS
//this is a header file
using namespace std;
class Node
{
public:
//key : frequency, value : code
int f;
char* code;
Node* left;
Node* right;
int getFrequency()
{
return f;
}
char* getCode()
{
return code;
}
void init(int frequency, char* codestring)
{
f = frequency;
code = codestring;
}
Node* getLeft() {
return left;
}
Node* getRight()
{
return right;
}
void setLeft(Node* L)
{
left = L;
}
void setRight(Node* R)
{
right = R;
}
void setFrequency(int frequency)
{
f = frequency;
}
void setCode(char* string)
{
code = string;
}
};
class BinaryTree
{
public:
typedef priority_queue<int, vector<int>, greater<int>> pq;
pq q;
Node* proot;
int sizeofqueue;
void init(pq PriorityQueue)
{
q = PriorityQueue;
sizeofqueue = q.size();
N = 0;
int comparetimes = q.size() - 1;
for (int i = 0; i < comparetimes; i++)
{
if (i == 0)
{
put_first_two_nodes();
}
else
{
if (proot->getFrequency() <= q.top())
{
put_right_node();
}
else if (proot->getFrequency() > q.top())
{
put_left_node();
}
q.pop();
}
}
}
void put_first_two_nodes()
{
Node* pleft = new Node();
(*pleft).setFrequency(q.top());
(*pleft).setCode("0");
q.pop();
Node* pright = new Node();
(*pright).setFrequency(q.top());
(*pright).setCode("1");
put(pleft, pright);
q.pop();
}
void put_right_node()
{
Node* pright = new Node();
pright->setFrequency(q.top());
pright->setCode("1");
put(proot, pright);
appendcode(0);
}
void appendcode(int prefix)
{
string pre;
if (prefix == 1) pre = "1";
else pre = "0";
Node* targetNode = proot->getRight();
char* rcode = targetNode->getRight()->getCode();
char* lcode = targetNode->getLeft()->getCode();
string lefts = pre;
string rights = pre;
lefts.append(lcode);
rights.append(rcode);
char* leftstring = strdup(lefts.c_str());
char* rightstring = strdup(rights.c_str());
targetNode->getLeft()->setCode(leftstring);
targetNode->getRight()->setCode(rightstring);
free(leftstring);
free(rightstring);
}
void put_left_node()
{
Node* pleft = new Node();
pleft->setFrequency(q.top());
pleft->setCode("0");
put(pleft, proot);
appendcode(1);
}
char* get(int k)
{
return getItem(*proot, k);
}
char* getItem(Node root, int k)
{
//if there's no node
if (&root == nullptr) return "";
//if f or root > k, search left sibling
if (root.getFrequency() > k) return getItem(*(root.getLeft()), k);
//else, search right sibling
else if (root.getFrequency() < k) return getItem(*(root.getRight()), k);
//get it
else return root.getCode();
}
void put(Node* left, Node* right)
{
put_item(left,right);
}
void put_item(Node* left, Node* right)
{
//make new node that has sibling with left and right
Node* newnode = new Node();
newnode->setLeft(left);
newnode->setRight(right);
//exchange the new node and root without losing data
Node* temp;
temp = proot;
proot = newnode;
newnode = temp;
//proot's frequency : left f + right f
(*proot).setFrequency((*left).getFrequency() + (*right).getFrequency());
}
void printpost()
{
postorder(proot);
}
void postorder(Node* root)
{
if (root != nullptr)
{
if (root->getLeft() != nullptr) postorder(root->getLeft());
if (root->getRight() != nullptr) postorder(root->getRight());
printf("%d : %s ",root->getFrequency(), root->getCode());
}
}
private:
int N;
Node root;
};
You shouldn't use const char* and char* at all in c++ (unless when sometimes dealing with legacy or foreign interfaces).
Switch up your code to use eg. std::string or std::string_view (c++17) instead (string_view requires a bit more understanding to handle correctly and is const so to speak - so I would stick to string off the bat). Pass std::string by reference or by const reference where neccesary. The overhead of std::string is for most programs negliable.

A star algorithm in c++

I am trying to implement A* search algorithm with priority_queues and I have drawn the output on the console with opengl.
I got this output: Final path with A star
Where the cells in gray weren't visited, in yellow were visited and the final path in blue.
I think that the cells that were visited should be less and closer to the path, or I am wrong?
I computed the path with the following code:
list<Node*> compute_path_A_star(Node* start, Node* goal)
{
priority_queue< nodeDistance, vector< nodeDistance >, CompareDist> pq;
vector<Node*> came_from;
vector<float> cost_so_far;
nodeDistance first;
first.node = start;
first.distance = 0.0f;
pq.push(first);
came_from.resize(20 * 20, nullptr);
cost_so_far.resize(20 * 20, 9999.0f);
cost_so_far[start->x + 20 * start->y] = 0.0f;
//Compute where we came from for every location that’s visited
int i = 0;
while (!pq.empty())
{
nodeDistance temp = pq.top();
pq.pop();
Node* current_node = temp.node;
current_node = get_node(current_node->x, current_node->y);
if (current_node == goal) break;
for (auto n : current_node->neighbours)
{
float new_cost = cost_so_far[current_node->x + 20 * current_node->y] + n->cost;
if (new_cost < cost_so_far[n->x + 20 * n->y])
{
cost_so_far[n->x + 20 * n->y] = new_cost;
came_from[n->x + 20 * n->y] = current_node;
nodeDistance newNode;
newNode.node = n;
newNode.distance = new_cost + heuristic(n, goal);
pq.push(newNode);
}
}
}
#pragma region Create the path (start -> goal)
Node* current = new Node();
current = goal;
list<Node*> path;
path.push_back(current);
while (current != start)
{
current = came_from[current->x + 20 * current->y];
path.push_back(current);
}
path.reverse();
#pragma endregion
return path;
}
I used Manhattan distance for the heuristic:
float heuristic(Node* a, Node* b)
{
//Manhattan distance on a square grid
return (abs(a->x - b->x) + abs(a->y - b->y));
}
nodeDistance is a struct:
struct nodeDistance
{
Node* node;
float distance;
};
And for the comparision in the priority queue I defined this class:
class CompareDist
{
public:
bool operator()(nodeDistance& n1, nodeDistance& n2)
{
if (n1.distance > n2.distance)
return true;
else
return false;
}
};
I defined each node as:
struct Node
{
int x, y;
float cost;
Node* parent;
list<Node*> neighbours;
};
And the graph:
list<Node*> Graph;
Edit 1:
For the A star implementation, I was based on this page http://www.redblobgames.com/pathfinding/a-star/introduction.html.
There is something that I missed? Thanks!
Edit 2:
I have inserted some obstacles (dark-gray cells) and waypoints (pink cells) on the scene. In red the goal cell

Optimization for 8 puzzle solutions to store in trees structure

I have a breadth first search to find the best solution to an 8 puzzle. In order to make sure I don't execute the same function call on the same puzzle move I have created a tree structure. It doesn't store the puzzle, just creates a pathway in the tree for the 9 values for the 9 slots in the puzzle. Here is the code:
static const int NUM_NODES = 9;
class TreeNode
{
public:
TreeNode *mylist[NUM_NODES];
TreeNode()
{
for (int x = 0; x < NUM_NODES; ++x)
mylist[x] = nullptr;
}
};
class Tree
{
private:
TreeNode *mynode;
public:
Tree()
{
mynode = new Node();
}
bool checkOrCreate(const Puzzle &p1)
{
Node *current_node = mynode;
bool found = true;
for (int x = 0; x < PUZZLE_SIZE; ++x)
{
for (int y = 0; y < PUZZLE_SIZE; ++y)
{
int index_value = p1.grid[x][y];
if (current_node->mylist[index_value] == nullptr)
{
found = false;
current_node->mylist[index_value] = new Node();
current_node = current_node->mylist[index_value];
}
else
current_node = current_node->mylist[index_value];
}
}
return found;
}
};
static Node* depth_Limited_Search(Problem &problem, int limit)
{
mylist.reset();
return recursive_Depth_Search(&Node(problem.initial_state, nullptr, START), problem, limit);
}
static Node *recursive_Depth_Search(Node *node, Problem &problem, int limit)
{
if (problem.goal_state == node->state)
return node;
else if (limit == 0)
return nullptr;
if (mylist.checkOrCreate(node->state)) //if state already exists, delete the node and return nullptr
return nullptr;
std::unique_ptr<int> xy(node->state.getCoordinates());
int xOfSpace = xy.get()[0];
int yOfSpace = xy.get()[1];
set <Action> actions = problem.actions(node->state); //gets actions
for (auto it = begin(actions); it != end(actions); ++it)
{
Action action = *it;
Node &child = child_node(problem, *node, action);
Node *answer = recursive_Depth_Search(&child, problem, limit - 1);
if (answer != nullptr)
return answer;
}
return nullptr;
}
static Node& child_node(Problem problem, Node &parent, Action action)
{
Node &child = *(new Node());
child.state = problem.result(parent.state, action);
child.parent = &parent;
child.action = action;
child.path_cost = parent.path_cost + problem.step_cost(parent.state, action);
return child;
}
Puzzle& result(const Puzzle &state, Action action)
{
// return a puzzle in the new state after perfroming action
Puzzle &new_state = *(new Puzzle(state));
int r = state.getCoordinates()[0], c = state.getCoordinates()[1];
if (action == UP)
new_state.swap(r, c, r - 1, c);
else if (action == RIGHT)
new_state.swap(r, c, r, c + 1);
else if (action == DOWN)
new_state.swap(r, c, r + 1, c);
else if (action == LEFT)
new_state.swap(r, c, r, c - 1);
return new_state;
}
I've used this on breadth and also on depth limited search using recursion to solve. Using this structure to store all the possible solutions for these algorithms takes a long time. I believe it has something to do with the allocation taking time. Is that the reason? I was thinking of trying to just create a lump of memory, and then assigning a node that address of memory instead of letting the program do it. Would that be the best solution, and how would I do that? (Since I've used this on multiple searches and they all take a long time to perform I haven't included that code.)

Inserting element into left leaning black red tree c++

I have been staring at this all day and have gotten slightly somewhere, but it's still not working correctly! Just trying to 'put' (really insert, or find if it's there) an element k into a LL red black tree. Here's my method:
Node * RPut(Node* p, const K& k, Node*& location)
{
// if you are at the bottom of the tree,
// add new node at bottom of the tree
if (p == 0)
{
// new red note with new data
location = NewNode(k, Data(), RED);
return location;
}
if(greater_(k,p->key_))
{
// if it's greater than the root, move down to the left child
p->left_ = Rput(p->left_, k, location);
}
// right subtree
else if (greater_(p->key_,k))
{
// but if the key is less than root, move down to right child
p->right_ = Rput(p->right_, k, location);
}
// if they are equal
else
{
location = p;
}
// code for rotating
// this sort of worked.
if(p->right_ && p->right_->IsRed())
{
p = RotateLeft(p);
if (p->left_->IsBlack())
{
p->SetBlack();
p->left_->SetRed();
}
}
if (p->left_ && p->left_->IsRed())
{ if (p->left_->left_ && p->left_->left_->IsRed())
{
p = RotateRight(p);
p->left_->SetBlack();
p->right_->SetBlack();
}
}
return p;
}
I know my rotate methods work perfectly. This inserts correctly until the fifth element (I haven't tried every combination, but usually.) For instance, abcde inserted correctly would be
d
b e
a c --
[with b as red node]
mine works but stops here, giving me:
b
a d
- - c e
with NO red nodes.
Anyone see anything obvious I am overlooking or why it isn't working properly? Any help at all much appreciated.
Thanks!
This does not directly answer the question, but have you read Sedgewick's paper on left-leaning red black trees? The code in it is exceptionally clear, there are beautiful diagrams explaining how things work, and, I imagine, it would be straight-forward to reimplement everything into C++.
Edit
I tried, for fun to implement Sedgewick's code. It turns out the paper had a few methods/subroutines left out that would have been pretty helpful to include. Anyway, my C++11 implementation, along with some tests, follows.
Since Java does automagic memory management, Sedgewick doesn't explicitly note where memory should be freed in his code. Rather than try to figure this out for a quick project and possibly leave memory leaks, I've opted to use std::shared_ptr, which provides a similar worry-free behaviour.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <memory>
template<class keyt, class valuet>
class LLRB {
private:
static const bool COLOR_RED = true;
static const bool COLOR_BLACK = false;
class Node {
public:
keyt key;
valuet val;
std::shared_ptr<Node> right;
std::shared_ptr<Node> left;
bool color;
Node(keyt key, valuet val){
this->key = key;
this->val = val;
this->color = COLOR_RED;
this->right = nullptr;
this->left = nullptr;
}
};
typedef std::shared_ptr<Node> nptr;
nptr root;
nptr rotateLeft(nptr h){
nptr x = h->right;
h->right = x->left;
x->left = h;
x->color = h->color;
h->color = COLOR_RED;
return x;
}
nptr rotateRight(nptr h){
nptr x = h->left;
h->left = x->right;
x->right = h;
x->color = h->color;
h->color = COLOR_RED;
return x;
}
nptr moveRedLeft(nptr h){
flipColors(h);
if(isRed(h->right->left)){
h->right = rotateRight(h->right);
h = rotateLeft(h);
flipColors(h);
}
return h;
}
nptr moveRedRight(nptr h){
flipColors(h);
if(isRed(h->left->left)){
h = rotateRight(h);
flipColors(h);
}
return h;
}
void flipColors(nptr h){
h->color = !h->color;
h->left->color = !h->left->color;
h->right->color = !h->right->color;
}
bool isRed(const nptr h) const {
if(h==nullptr) return false;
return h->color == COLOR_RED;
}
nptr fixUp(nptr h){
if(isRed(h->right) && !isRed(h->left)) h = rotateLeft (h);
if(isRed(h->left) && isRed(h->left->left)) h = rotateRight(h);
if(isRed(h->left) && isRed(h->right)) flipColors (h);
return h;
}
nptr insert(nptr h, keyt key, valuet val){
if(h==nullptr)
return std::make_shared<Node>(key,val);
if (key == h->key) h->val = val;
else if(key < h->key) h->left = insert(h->left, key,val);
else h->right = insert(h->right,key,val);
h = fixUp(h);
return h;
}
//This routine probably likes memory
nptr deleteMin(nptr h){
if(h->left==nullptr) return nullptr;
if(!isRed(h->left) && !isRed(h->left->left))
h = moveRedLeft(h);
h->left = deleteMin(h->left);
return fixUp(h);
}
nptr minNode(nptr h){
return (h->left == nullptr) ? h : minNode(h->left);
}
//This routine leaks memory like no other!! I've added a few cleanups
nptr remove(nptr h, keyt key){
if(key<h->key){
if(!isRed(h->left) && !isRed(h->left->left))
h = moveRedLeft(h);
h->left = remove(h->left, key);
} else {
if(isRed(h->left))
h = rotateRight(h);
if(key==h->key && h->right==nullptr)
return nullptr;
if(!isRed(h->right) && !isRed(h->right->left))
h = moveRedRight(h);
if(key==h->key){
std::shared_ptr<Node> mn = minNode(h->right);
h->val = mn->val;
h->key = mn->key;
h->right = deleteMin(h->right);
} else {
h->right = remove(h->right, key);
}
}
return fixUp(h);
}
void traverse(const nptr h) const {
if(h==nullptr)
return;
traverse(h->left);
std::cout<< h->key << "=" << h->val <<std::endl;
traverse(h->right);
}
public:
LLRB(){
root = nullptr;
}
void traverse() const {
traverse(root);
}
valuet search(keyt key){
nptr x = root;
while(x!=nullptr){
if (key == x->key) return x->val;
else if (key < x->key) x=x->left;
else x=x->right;
}
return keyt();
}
void insert(keyt key, valuet val){
root = insert(root,key,val);
root->color = COLOR_BLACK;
}
void remove(keyt key){
root = remove(root,key);
root->color = COLOR_BLACK;
}
};
int main(){
for(int test=0;test<500;test++){
LLRB<int,int> llrb;
std::vector<int> keys;
std::vector<int> vals;
for(int i=0;i<1000;i++){
//Ensure each key is unique
int newkey = rand();
while(llrb.search(newkey)!=int())
newkey = rand();
keys.push_back(newkey);
vals.push_back(rand()+1);
llrb.insert(keys.back(),vals.back());
}
//llrb.traverse();
for(int i=0;i<1000;i++){
if(llrb.search(keys[i])!=vals[i]){
return -1;
}
}
for(int i=0;i<500;i++)
llrb.remove(keys[i]);
for(int i=500;i<1000;i++){
if(llrb.search(keys[i])!=vals[i]){
return -1;
}
}
}
std::cout<<"Good"<<std::endl;
}