I'm trying to implement some basic Tree structure for sea navigation algorithm.
I've got something like this:
class Point {
float lng;
float lat;
};
class Node {
public:
Node *parent;
std::list<Node> *childern;
Point *point;
Node::Node(Node *prnt, Point *point);
void Node::calcChildrens();
};
Node::Node(Node *prnt, Point *point) {
this->parent = prnt;
this->point = point;
this->childern = nullptr;
}
int counter = 0;
void Node::calcChildrens() {
for (int i = 0; i < 5; i++) {
Point *p = new Point(someValX, someValY);
Node n = Node(this, p);
if (this->childern == NULL) this->childern = new list<Node>;
this->childern->push_back(n);
if (counter < 4) {
counter++;
n.calcChildrens();
}
}
This should create 4 level's of recursion tree, but creates just one level of tree.
I think it's the problem with parent pointers but i can't realize what really is happening.
There are several issues with your code
struct Point { // we want public access, hence struct not class
float lng;
float lat;
};
struct Node { // if all members a public, use struct
Node*parent = nullptr; // provide default argument
std::list<Node> children; // hold a list, not a pointer to one
Point point; // hold a Point, not a pointer to one
Node(Node*p, const Point&x)
: parent(p), point(x) {} // use initialization list
void calcChildren(size_t levels); // avoid global variable counter; use correct English
};
void Node::calcChildren(size_t levels)
{
if(levels--)
for(int i = 0; i < 5; i++) { // really 5? 4 children seems more logical
// construct child in place, avoid copying a Node
children.emplace_back(this, Point{someValX, someValY});
children.back().calcChildren(levels);
}
}
You may also keep track of the tree depth as a data member for each node. Unfortunately, as you failed to provide a Minimal Complete and Verifiable Example, I cannot test this here.
Note also that your code had no destructor for Node, leaking all memory allocated with a node. This problem disappears when avoiding those pointers is favour of objects. As Nodes are allocated on the heap anyway, this is the logical and correct way of doing things in C++.
Note further that you may want to avoid keeping the children in a linked list (linked lists are to be avoided if efficiency is important). You may instead use an array or vector. In this case
struct Node { // if all members a public, use struct
Node*parent = nullptr; // provide default argument
std::vector<Node> children; // hold a vector, not a pointer to one
Point point; // hold a Point, not a pointer to one
Node(Node*p, const Point&x)
: parent(p), point(x) {} // use initialization list
void calcChildren(size_t levels); // avoid global variable counter; use correct English
};
void Node::calcChildren(size_t levels)
{
if(levels--) {
children.reserve(5);
for(int i = 0; i < 5; i++) {
// construct child in place, avoid copying a Node
children.emplace_back(this, Point{someValX, someValY});
children.back().calcChildren(levels);
}
}
}
Related
I've been attempting to create a node class which mimics a node on a graph. Currently, storage of the predecessor and successor nodes are stored via a node pointer vector: std::vector<Node*> previous. The vectors for the predecessor/successor nodes are private variables and are accessible via setters/getters.
Currently, I am dealing with updating the pointer values when adding a new node. My current method to update the predecessor/successor nodes is through this method (the method is the same for successor/previous nodes, just name changes):
void set_next(std::vector<Node*> new_next) {
this->next.clear();
for (Node* node : new_next) {
this->next.push_back(node);
}
}
This works for the current node but I was wondering the best way to update the new_next nodes that are passed in, especially the most 'C++'-esque way to accomplish this. I have previously written a method which adds individual nodes to the successor/predecessor vector:
void add_next(Node* new_node, bool one_way = false) {
this->next.pushback(new_node);
if (!one_way) {
new_node->add_prev(this, one_way = true);
}
}
The one_way variable was used to determine the depth(?) of the add_next() call. If it is true, it will add to the successor set and then add to the predecessor set of new_node. Since the boolean value is set to false when the new_node->add_next() method call occurs, it will only add to the predecessor set and not attempt to call add_next()/add_prev() again. This solution does work, but I'd rather not have the one_way variable and would prefer that the method would be private.
Here is the structure of the class currently:
class Node {
private:
std::vector<Node*> previous;
std::vector<Node*> next;
boost::any data;
public:
std::vector<Node*> get_previous()
void set_previous(std::vector<Node*> new_previous)
std::vector<Node*> get_next()
void set_next(std::vector<Node*> new_next)
void add_prev(Node* new_node, bool one_way = false)
void add_next(Node* new_node, bool one_way = false)
}
Avoiding the one_way parameter, it seems my best solution would be to just create an add_next/add_prev method that only updates the current node, not the passed node, unlike the solution above. With this solution, when adding new nodes, I could call the inverse of the add_next/add_prev on the new node. However, I have an inkling there may be a better solution for this.
Thank you!
I think this should get you going (edge-cases left to you to figure out, if any):
template<typename T>
class Node {
// Everything made public for debugging purposes, change this to fit your needs
public:
std::vector<Node<T>*> previous;
std::vector<Node<T>*> next;
T data;
Node(T val) {
data = val;
}
void set_next(std::vector<Node<T>*>& new_next);
};
template<typename T>
void Node<T>::set_next(std::vector<Node<T>*>& new_next) {
next = new_next;
for (Node<T>* node : new_next)
node->previous.push_back(this);
}
int main() {
// Little proof of concept where 0 is parent to 1, 2, 3
Node<int> one = 1;
Node<int> two = 2;
Node<int> three = 3;
Node<int> zero = 0;
std::vector<Node<int>*> new_next = { &one , &two, &three };
zero.set_next(new_next);
return 0;
}
To sum up the differences:
Use templates, boost::any is non standard and is all around terrible for this task.
Leverage operators (= makes a copy of std::vectors).
Leverage reference types (this way you can modify the argument passed to your function).
I'm not sure how to describe this. I have to iterate through objects which are connected by pointers with each other, However the first element shouldn't have values stored in its class just the pointer to the next element.
I came up with a small class hierarchy. If I use it like that I have to cast the base class to the derived element. It only seems to work with a dirty cast.
Is there a better solution?
Here the example code:
#include <iostream>
struct Basenode {
Basenode* next;
};
struct Skipnode : Basenode {
Skipnode(int in_key, int in_value);
int key;
int value;
};
Skipnode::Skipnode(int in_key, int in_value)
: key{ in_key }, value{ in_value }
{
}
int main()
try {
Basenode head; // no key and value
Skipnode first(4, 2); // key and value
Skipnode second(8, 2);
Basenode* p = &head;
head.next = &first; // fine
first.next = &second; // fine
// p = p->next->key; // not accesible because is Basenode not derrived Skipnode
std::cout << static_cast<Skipnode*>(p->next)->key; // fine but diryt cast slicing ?
std::cin.get();
}
catch (std::runtime_error& e) {
std::cerr << e.what() << "\n";
std::cin.get();
}
catch (...) {
std::cerr << "unknown error " << "\n";
std::cin.get();
}
Edit: it was asked int the comments why i need this anyway. I think i gave a to limited example.
I need it to implement a skiplist. Many algorithms of it require to start on a element before the first element. The head element. I could make it a normal node and put in dummy values for the values but it didnt seem right. So now i came up with this ugly solution from youre suggestions to start on the head elements.
Heres a snippet with the copy constructor as example.
class Skiplist {
public:
//...
Skiplist(const Skiplist& other); // copy constructor
//...
private:
struct Skipnode; // forward declaration so Basenode can have Skiplist*
struct Basenode { // Empty node, mainly created to represent head element.
// Is there a way to get a empty head with no key / values without using this ?
Basenode(int in_level);
Basenode(const std::vector<Skipnode*>& in_next);
std::vector <Skipnode*> next;
};
struct Skipnode : Basenode { // derived so with Basenode* we can start the iteration of the node on head
Skipnode(value_type val, int in_level);
Skipnode(value_type val, const std::vector<Skipnode*>& in_next);
value_type value; // first key / second mapped type = value
//key_type key;
//mapped_type value;
};
Basenode head{ 0 }; // element before first element containg pointers to all the first elements of each level
//...
};
Skiplist::Skiplist(const Skiplist& other) // copy constructor
:head{ other.head }, top_level{ other.top_level }, random_engine{ other.random_engine }
// on the first level let the other Skiplist present its elements and make a deep copy of them
// now still the higher levels point to the other node so this is fixed in the second part
// then the next level pointers are installed linked to the elements of the new node
{
if (top_level == 0) return; // no elements are present so dont bother to allocate nodes
{
// installment of lowest level, each element is located here
Skipnode* other_node = other.head.next[0];
Basenode* current_position = &head;
while (other_node != nullptr) {
Skipnode* new_node = new Skipnode{ other_node->value,other_node->next };
current_position->next[0] = new_node;
current_position = current_position->next[0];
other_node = other_node->next[0];
}
current_position->next[0] = nullptr;
}
// installment of the other levels
for (size_type curr = 1; curr < top_level; ++curr) {
Basenode* current_position = &head; // the current position of the level[curr]
Skipnode* next_position = current_position->next[curr]; // next position after curr containing still pointers to the other skiplist
Basenode* lowest_position = &head; // lowest level position used to find the new pointers and attach them "behind" current
while (lowest_position != nullptr && next_position != nullptr) {
if (lowest_position->next[0]->value.first == next_position->value.first) { // check by unique key, address of next pos is still of the other skiplist
current_position->next[curr] = lowest_position->next[0]; // lowest is the valid address of new node
current_position = current_position->next[curr];
next_position = next_position->next[curr]; // go to next element of other node
if (next_position == nullptr) { // case end is reached
current_position->next[curr] = nullptr;
current_position = current_position->next[curr];
}
}
else { // forward position of lowest level until other key == next position key
lowest_position = lowest_position->next[0];
}
}
}
}
See here for a basic explanation how a skiplist is organized:
https://en.wikipedia.org/wiki/Skip_list
The whole code is on codereview:
https://codereview.stackexchange.com/questions/197752/non-generic-skip-list-implementation-in-c-version-2
All the things #SomeProgrammerDude is saying, or:
I don't see a need for class BaseNode at all. Why can't we just have (all other things being equal):
SkipNode *head = &first;
...
Or better yet a class called (for example) SkipNodeList that handles all aspects of managing and iterating through a list of SkipNodes.
Of course, this is all a bit silly anyway, just use std::list (or std::forward_list) for this and benefit from all that STL goodness.
Or you can derive from one of these to add your own functionality (such as a mutex to make the list threadsafe or keeping track of the number of elements currently in the list, as suggested by #iMajuscule).
Yes, there is a better way:
Forward-declare Skipnode, and in BaseNode, use a pointer to SkipNode, this way you don't have to cast:
struct Skipnode;
struct Basenode {
Skipnode* next;
};
Also, to illustrate how this design where Skipnode inherits from Basenode could make sense (related to the discussion in the comments), we can imagine having a member in Basenode counting how many elements are next (counting the one in the next member and its successors)
I have been solving a question, Dijkstra's Algorithm, in C++. I've implemented it using adjacency list.
So I have a class for a node, a class for a minHeap, and a class for the Graph.
class node
{
int vertex,weight;
node *next;
friend class Graph;
friend class minHeap;
public:
node();
node(int,int);
};
node::node(){
vertex=weight=0;
next=0;
}
node::node(int v,int wt){
vertex=v;
weight=wt;
next=0;
}
Do I define the minHeap class this way (without a friend function) and create an object in the getDijkSP() function normally, which allows me to use the object only in that function?
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap];
heapSize=-1;
pos=new int[cap]();
} //eliminating other methods
class Graph
{
node **adjList;
int v;
bool *visited;
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
}
void Graph::getDijkSP(){
minHeap hp(v); //here
hp.addElement(node(0,0));
for(int i=1;i<v;i++)
hp.addElement(node(i,INT_MAX));
while(!hp.isempty()){
node temp=hp.extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp.decreaseKey(current->vertex,current->weight+temp.weight);
}
}
(OR) Do I define the minHeap class with a friend function, so that I can create an object of the minHeap class using the new keyword? (And this helps me define the minHeap object in the scope of the Graph class, so that I can use it in all of its functions for other capabilities as well.)
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
friend class Graph; //say like this
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap]();
heapSize=-1;
pos=new int[cap]();
}
class Graph
{
node **adjList;
int v;
bool *visited;
minHeap *hp; //and do this
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
hp=new minHeap(v); //dynamic allocation
}
void Graph::getDijkSP(){
hp->addElement(node(0,0));
for(int i=1;i<v;i++)
hp->addElement(node(i,INT_MAX));
while(!hp->isempty()){
node temp=hp->extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp->decreaseKey(current->vertex,current->weight+temp.weight);
}
}
I have read this and a few other articles, but specifically want to know the advantages, disadvantages and the appropriateness of both the methods for such similar kinds of questions.
I've provided the constructors for the classes for better clarity.
Short answer would be NO. I would suggest you to read up on smart pointers and rewrite this whole mess. In C++ there is no real reason to use manual allocation in so simple project as this ever.
Also instead of assigning 0 or NULL to a pointer use nullptr, which is C++ symbol only for null pointers unlike the previous mentioned C values that are actually just a int 0 which may cause some unintentional errors.
Edit in response to your comment:
So I've decided to rewrite your code using actual modern C++ instead of this C code with simple classes. In your whole example there are almost no pointers or dynamic allocations needed. I wasn't absolutely sure who exactly should own the actual nodes so from the example I assumed that the MinHeap should. Also I didn't get the point of MinHeap::pos and Graph::visited from what I could see. I can explain any part of that code in more detail, just ask which.
Here is the code:
class Node {
// Only friend class required if you insist on keeping members of Node private.
// If they aren't meant to change, consider declaring them as public and const.
template <unsigned Size> friend class Graph;
public:
Node(int v, int wt) : vertex(v), weight(wt) {}
private:
// Default values written in here right after declarations
// There is no need for a default constructor. You never call it anyway.
int vertex;
int weight;
Node* next = nullptr;
};
// Template parameter because of internal use of std::array.
// If the capacity shouldn't be constant, use std::vector and remove template.
template <unsigned Capacity>
class MinHeap {
public:
// No constructor needed
// ---------------------
// One small tip: write parameter names in function declarations
// even if they aren't needed there for better readability of your code.
void addElement(Node n) { /* impl */ }
Node extractMin() { /* impl */ }
unsigned capacity() { return Capacity; }
bool isEmpty() { return heap.isEmpty(); }
private:
// Default values written in here right after declarations
int heapSize = -1;
std::array<Node, Capacity> heap;
};
// Template parameter because of internal use of std::array.
// If the vertex count shouldn't be constant, use std::vector and remove template.
template <unsigned Vertices>
class Graph {
public:
// No constructor needed
// ---------------------
void getDjikSP() {
hp.addElement({0, 0});
for (unsigned i = 1; i < hp.capacity(); ++i)
hp.addElement({0, INT_MAX});
while (!hp.isEmpty()) {
Node tmp = hp.extractMin();
std::cout << tmp.vertex << " " << tmp.weight << std::endl;
for (Node* current = adjList[tmp.vertex]; current != nullptr; current = current->next)
hp.decreaseKey(current->vertex, current->weight + tmp.weight);
}
}
private:
// Default values written in here right after declarations
std::array<Node*, Vertices> adjList;
MinHeap<Vertices> hp;
};
There is still a lot of space for improvements of this code, for example the MinHeaP::extractMin should maybe return Node&& if it is removed from the heap or const Node& if it should return a reference to the top, etc. To address all the problems and inefficiencies this can still have I would need to see the full code with all functions.
struct Node{
Node* ch[26];
string str;
Node(){
for(int i = 0; i < 26; i++) {
ch[i] = NULL;
}
str = "";
}
};
class Solution {
public:
vector<string> results;
Node* root;
void insert(Node* p, string s) {
int len = s.size();
for(int i = 0; i < len; i ++) {
if(p->ch[s[i] - 'a'] == NULL) {
p->ch[s[i] - 'a'] = new Node();
}
p = p->ch[s[i] - 'a'];
}
p->str = s;
}
vector<string> wordSearchII(vector<vector<char> > &board, vector<string> &words) {}
}
This is the Trie I defined for my problem. The "root" and "vector result" are both member variables of Solution. The question I want to ask is that why I must "new Node()" before I use root. I do not need to "new vector" before I use results. I understand that the Solution will call default constructor and then "results" will call its default constructor. Why couldn't root use the default constructor of Node?
I happen to realize that my confuse may relate to "pointer". But I still don't understand the details. Can anyone explain about it? I really appreciate it.
root is just a pointer, but you are not assigning anything for it to point at. You need to allocate a new Node object and then assign the address of that object to root, eg:
class Solution {
public:
vector<string> results;
Node* root;
Solution() {
root = new Node;
}
~Solution() {
delete root;
}
...
};
Otherwise, don't make root be a pointer at all:
class Solution {
public:
vector<string> results;
Node root;
...
};
On a side note, your Node class needs a destructor to destroy any child nodes that are added to it:
struct Node{
Node* ch[26];
string str;
Node(){
for(int i = 0; i < 26; i++) {
ch[i] = NULL;
}
}
~Node(){
for(int i = 0; i < 26; i++) {
delete ch[i];
}
}
};
In
Node* root;
The * means that root is a pointer to a Node object, it is not an actual Node object itself. The only storage a pointer has is enough to hold the memory address of whatever the pointer is pointing at. A pointer has to point at something. Right now, you have no idea what root points at, and this is... bad. You have no idea what you'll get if you try to read from it, and you have no idea what you'll smash if you try to write to it. You need to assign something for root to point at, and if that's a new Node(), so be it, but it could also be a pre-existing Node, or a Node in automatic storage (AKA somewhere on the stack).
On the other hand, in
vector<string> results;
results is not a pointer to a vector object. It is the actual vector object. It is the storage. There is no need to allocate memory for it, simply declaring it on the stack allocates everything for it and calls its default constructor.
This is not a real question, since I've already solved the problem myself, but I still need some clarifications about the mechanism behind assigning an array's address to a pointer of the same type when the array is a class member of a nested class.
The following code is fully functioning, although it may lack some error_check. It is only meant to show how I made my (real) program work.
HEADER (linkedList)
class linkedList
{
public:
linkedList();
~linkedList();
int* getArray();
void forward();
private:
class listNode
{
public:
listNode();
~listNode();
friend class linkedList;
private:
int array[3];
listNode* next;
};
listNode *first;
listNode *current;
};
CPP (linkedList)
linkedList::linkedList()
{
first = new listNode;
current = first;
}
//~~~~~~~~~~~~
linkedList::~linkedList()
{
delete first;
first = 0;
current = 0;
}
//~~~~~~~~~~~~
int* linkedList::getArray()
{
if (current)
{
return &(current->array[0]);
}
}
//~~~~~~~~~~~~
void linkedList::forward()
{
if (current->next)
{
current = current->next;
}
}
//-------------------------
//-------------------------
//-------------------------
linkedList::listNode::listNode()
{
next = 0;
for (int i = 0; i < 3; i++){array[i]=((i+1)*3);}
}
//~~~~~~~~~~~~
linkedList::listNode::~listNode()
{
}
CPP (main)
#include <iostream>
#include "linked_list.h"
using namespace std;
int main()
{
linkedList list;
int *myArray;
myArray = list.getArray();
for (int i = 0; i < 3; i++){cout << myArray[i] << " ";}/**/cout << "\n\n";
return 0;
}
The real program is meant to move through a linked list made of nodes which contain 3 integer values in an array of int type, retrieve the three values and use them as parameters for some other functions.
Now, to do so I have to return the address to the first element of the array contained in the node through an accessor.
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
Why?
I've got to this solution through trial and error with very little knowlegde of the reasons that brought me to build this expression as it is.
Usually, when you want to assign the address of an array to a pointer, you just do so:
int main()
{
int array[3];
int* pArray;
pArray = array;
}
And that's it, because the name of the array itself is enough to retrieve the address of its first element.
The exact same result can be achieved by doing this (tested):
int main()
{
int array[3];
int* pArray;
pArray = &(array[0]);
}
Both methods are also valid when the accessor returns the address from a member variable of its own class.
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
What are the logic stages that make it the only viable method?
But why, when accessing the member variable of a nested class, I'm forced to use the second method?
You aren't:
return current->array;
and
return &(current->array[0]);
Both do the same thing when the return type is int*. You aren't forced to use the second way.
Also, there's a bug in getArray. You don't return anything if current is null.
To be pedantic...
Apparently, the only way to do it is by returning the reference to the first element of the array in the node to which the linkedList's member variable current points to:
return &(current->array[0]);.
You're returning the address i.e. a pointer. Reference means something else.