I have structure:
struct node
{
bool data;
node* l;
node* r;
node(bool data_) : data(data_), l(0), r(0) {}
};
And loop like this
void printNode(std::vector<node*> nodes, int level, int max_level)
{
for (int i = 0; i < nodes.size(); i++) {
node * itr = nodes.at(i);
if (itr->data != 2) {
cout << itr->data;
newNodes.push_back(itr->l);
newNodes.push_back(itr->r);
} else {
newNodes.push_back(new node(2));
newNodes.push_back(new node(2));
cout << " ";
}
printWhitespaces(betweenSpaces);
}
}
Some times itr->l(or r) is null, not init struct. How i can check this ?
Something like this? It will skip your NULL elements, and elements with NULL value for r member of the vector and continue the for loop.
node * itr = nodes.at(i);
if(!itr || !itr->r) continue;
To check if a pointer is null simply use:
itr->l == 0
If it is 0 it is null. But consider using smart pointers, they are much safer.
You should also considering iterating over your vector the standard way, using something like this:
std::vectoc<node*>::iterator
it = nodes.begin(),
ite = nodes.end();
for(; it != ite; ++it) {
...
}
And finally you should probably be passing your vector by reference like this:
void printNode(std::vector<node*>& nodes, int level, int max_level)
Related
Feel free to point out my mistakes, I do not claim to be a good C++ programmer or even good w/ Data structures. I'm just looking to improve and learn upon my example.
This approach is not my own but the code is. I learned a concept and attempted to code it in C++.
The point here is to learn to build this without using libraries such as std::priority_queue. Thanks again!
#include <iostream>
#include <memory>
#include <vector>
#include <unordered_map>
#include <algorithm>
// directions of each node
enum
{
IS_LEFT = 1,
IS_RIGHT = 2
};
// (ADT) Priority Queue which uses a (DS) heap
using std::vector;
// Makes removal of any node anywhere within the heap O(log(n))
using std::unordered_map;
class BinaryStack
{
private:
// tracks the last node in heap
size_t last_index { 0 };
// the heap
vector<int> heap{ };
// the hashmap to track where any given node is at (required for node removal within a heap)
unordered_map<int, vector<size_t>> hashmap{ };
// swap any two values from two given vectors
void swapVectorValue(vector<size_t> &vec1, size_t val1, vector<size_t> &vec2, size_t val2)
{
vec1.erase(std::remove(vec1.begin(), vec1.end(), val1), vec1.end());
vec2.erase(std::remove(vec2.begin(), vec2.end(), val2), vec2.end());
vec1.push_back(val2);
vec2.push_back(val1);
}
// adds a value to hashmap | the keys are the node values & the values are their respective indexes
void addToHashMap(int val, size_t last_index)
{
auto search = hashmap.find(val);
if (search != hashmap.end())
hashmap[val].push_back(last_index);
else
hashmap[val] = vector<size_t> { last_index };
}
public:
// insert a node into the heap
void insert(int val)
{
heap.push_back(val);
// point last node to end of array
size_t last_index = heap.size()-1;
addToHashMap(val, last_index);
// only one node so lets just stop here
if (heap.size() == 1) return;
// determines if node is on left or right
short node_direction = (heap.size() % 2 == 0) ? IS_LEFT : IS_RIGHT;
size_t parent_index = (last_index - node_direction) / 2;
// keep going until bubbles to top
while (heap[parent_index] > heap[last_index])
{
//swaps indexes of swapped nodes
swapVectorValue(hashmap[heap[parent_index]], parent_index, hashmap[heap[last_index]], last_index);
// update value of parent and new node
int temp { heap[parent_index] };
heap[parent_index] = heap[last_index];
heap[last_index] = temp;
// leave if at top
if (parent_index == 0) break;
// find new parent
last_index = parent_index;
node_direction = (last_index % 2 == 0) ? IS_RIGHT : IS_LEFT;
parent_index = (last_index - node_direction) / 2;
}
}
// remove any node
void remove(int val)
{
size_t parent_index{ };
auto search = hashmap.find(val);
if (search != hashmap.end())
{
parent_index = hashmap[val].back();
hashmap[val].pop_back();
if (hashmap[val].size() == 0) hashmap.erase(val);
} else return;
last_index = heap.size()-1;
heap[parent_index] = heap[last_index];
heap.pop_back();
size_t left_child = (parent_index * 2) + 1;
size_t right_child = (parent_index * 2) + 2;
size_t smallest_child{ };
if (left_child > last_index) return;
if (left_child == last_index && heap[left_child] > heap[parent_index]) return;
if (right_child > last_index)
smallest_child = left_child;
else
smallest_child = (heap[left_child] < heap[right_child]) ? left_child : right_child;
while (heap[parent_index] > heap[smallest_child])
{
swapVectorValue(hashmap[heap[parent_index]], parent_index, hashmap[heap[smallest_child]], smallest_child);
// update value of parent and new node
int temp { heap[parent_index] };
heap[parent_index] = heap[smallest_child];
heap[smallest_child] = temp;
parent_index = smallest_child;
left_child = (parent_index * 2) + 1;
right_child = (parent_index * 2) + 2;
if (left_child > last_index) return;
if (left_child == last_index && heap[left_child] > heap[parent_index]) return;
if (right_child > last_index)
smallest_child = left_child;
else
smallest_child = (heap[left_child] < heap[right_child]) ? left_child : right_child;
}
}
// removes only the top node
int poll(int val)
{
// NOT PROGRAMMED YET
return 1;
}
void display()
{
// get parent node
for (const auto &n: heap)
{
std::cout << n << ' ';
}
std::cout << std::endl;
}
void hashmapDisplay()
{
for (const auto& r: hashmap)
{
std::cout << "value: " << r.first << " at indexes: ";
for (const auto& s: r.second)
{
std::cout << s << ' ';
}
std::cout << std::endl;
}
}
};
int main()
{
std::unique_ptr<BinaryStack> bstack(new BinaryStack());
bstack->insert(95);
bstack->insert(9);
bstack->insert(9);
bstack->insert(12);
bstack->insert(14);
bstack->insert(9);
bstack->insert(93);
bstack->remove(93);
bstack->remove(9);
// proves order of heap
bstack->display();
// just to prove the indexes are being tracked correctly
bstack->hashmapDisplay();
return 0;
}
Here's my stack:
template <class Type>
struct Node {
Type value;
Node* next;
Node(Type n_value)
: value(n_value), next(nullptr)
{ }
static Node<Type>* Add(Node<Type>* head, const Type value) {
if (!head) { head = new Node<Type>(value); }
else { head->next = Add (head->next, value); }
return head;
}
static void Remove(Node<Type>* head) {
if (head->next) { Remove(head->next); }
else { delete head; }
}
static void Empty(Node<Type>* head) {
if (head->next) { Empty(head->next); }
delete head;
}
static void Display(const Node<Type>* head) {
std::cout << "\nBEGINNING\n";
std::function<void(const Node<Type>*)> DisplayElements = [&] (const Node<Type>* head) {
if (head) {
std::cout << head->value << std::endl;
if (head->next) { DisplayElements(head->next); }
}
};
DisplayElements(head);
std::cout << "\nEND\n";
}
};
With following code:
auto beg = Node<int>::Add(nullptr, 0);
for (int i = 0; i < 10; i++) { Node<int>::Add(beg, i); }
Node<int>::Display(beg);
Node<int>::Empty(beg);
Everything is okay:
BEGINNING
0
0
1
2
3
4
5
6
7
8
9
END
Program ended with exit code: 0
But when I try to remove something:
auto beg = Node<int>::Add(nullptr, 0);
for (int i = 0; i < 10; i++) { Node<int>::Add(beg, i); }
Node<int>::Remove(beg);
Node<int>::Remove(beg);
Node<int>::Display(beg);
Node<int>::Empty(beg);
return 0;
I get Pointer being freed was not allocated on delete head; in Remove. Why? It's absolutely the same as Empty (which erases whole list), except it deletes only last node. Empty works fine.
Empty is needed to delete whole list (so that we don't get memory leaks), and Remove is to remove last element.
I am unable to reproduce your results, so instead of an answer, I am providing a nudge on how you might proceed.
I changed the parameter of DisplayElements to 'lhead' (for local head), because the 'head' declaration shadow's the one in the outer scope. You also have some other shadows ... so I recommend you add -Wshadow to your compiler settings.
I also added to your Display() function some diagnostic hex output.
static void Display(const Node<Type>* head)
{
std::cout << "\nBEGINNING\n";
std::function<void(const Node<Type>*)> DisplayElements =
[&] (const Node<Type>* lhead)
{
if (lhead)
{ // vvvvvvvvvvvv--diagnostic only
std::cout << hex << lhead << " " << dec
<< lhead->m_value << std::endl;
if (lhead->m_next)
{
DisplayElements(lhead->m_next);
}
}
};
DisplayElements(head);
std::cout << "\nEND\n";
}
And in addition ... I changed the following. By avoiding the Empty() and the other couple of lines, the first display will more closely match the second:
auto beg = Node<int>::Add(nullptr, 0);
{
for (int i = 0; i < 10; i++) { Node<int>::Add(beg, i); }
Node<int>::Display(beg);
// Node<int>::Empty(beg);
}
{
// auto beg = Node<int>::Add(nullptr, 0);
// for (int i = 0; i < 10; i++) { Node<int>::Add(beg, i); }
Node<int>::Remove(beg);
Node<int>::Remove(beg);
Node<int>::Display(beg);
Node<int>::Empty(beg);
}
Now consider connecting the debugger and setting a break point to inspect what "Remove()" is doing.
Don't be shy about adding more diagnostic cout's.
What I notice is:
a) that the last lines of output are an infinite loop.
b) outputs for values 1..8 are identical to the first,
c) the output for value 9 is missing ... and I suppose should be ... but something about that last Node (perhaps the one with 8?) must be confused.
I have written one simple graph Adj Matrix from one Adj List from gitHub .
The first one is Adj list,
Second is Adj matrix.
The first One work well. But the second is wrong with int Num which represent the vertices number like the first one int numOfVertices.
It seed like the 'int Num' become a read only variable. It crash into Process finished with exit code 11 .
I have looked for wiki to find "segmentation default", there are 4 reasons , one of them is trying to modify a read only
variable.
Then I cancel the modify for "Num" in constructor for the Adj Matrix. It work well.
But I don't know why the first one is well but the second is wrong? And how to solve it? Because I need to modify the value of Num...
The Adj List code
#ifndef ALTHGORITHM_GRAPH_ADJ_LIST_H
#define ALTHGORITHM_GRAPH_ADJ_LIST_H
#include <iostream>
#include <vector>
#include <queue>
namespace graph_adj_list {
template <class dataType> // Type of data vertex will hold
class Graph {
int numOfVertices; // number of vertices.
struct Vertex; // forward declaration of vertex structure
struct Node { // linkedlist for mapping edges in the graph
Vertex * vertexPtr; // points to the vertex to which the edge is adjecent
Node * next; // points to the next edge belonging to same vertex
};
enum visitedState{ // Enum representing visited state of vertex
WHITE, // not yet visited
GRAY, // being visited
BLACK // visited
};
struct Vertex {
visitedState state; // state of vertex, visited/being visited/done
dataType data; // the template data
Node * list; // Pointer to all edges (linkedlist)
};
std::vector<Vertex> vertices; // vector of all vertices.
//private methods
Node * getNode( Vertex * ); // allocate and initialize a newnode for the adj list.
void insertAtEnd( Node * & , Vertex * ); // insert at the end of adjacency list of vertex.
void deleteAllAfter( Node * ); // delete the adjacency list of the vertex.
public:
Graph() = default; // Default constructor
Graph(std::vector<dataType> &);
~Graph();
}
template <typename dataType>
typename Graph<dataType>::Node *
Graph<dataType>::getNode(Vertex * v) // allocate and initialize a newnode for the adj list.
{
Node * newNode = new Node;
newNode->vertexPtr = v;
newNode->next = nullptr;
return newNode;
}
template <typename dataType>
void Graph<dataType>::insertAtEnd( Node * & node, Vertex * v) // insert at the end of adjacency list of vertex.
{
Node *newNode = getNode(v);
if ( node == nullptr ) {
node = newNode;
} else {
Node * temp = node;
while( temp->next != nullptr ) {
temp = temp->next;
}
temp->next = newNode;
}
}
template <typename dataType>
void Graph<dataType>::deleteAllAfter( Node * node ) // delete the adjacency list of the vertex.
{
Node * nextNode;
while( node != nullptr ) {
nextNode = node->next;
delete(node);
node = nextNode;
}
}
template <typename dataType>
Graph<dataType>::Graph(std::vector<dataType> & values) // Non default constructor, takes a vector of vertices data
: numOfVertices(values.size()),
vertices(numOfVertices)
{
for ( int i = 0; i < numOfVertices; ++i ) {
vertices[i].data = values[i];
vertices[i].list = nullptr;
vertices[i].state = WHITE;
}
}
template <typename dataType>
Graph<dataType>::~Graph()
{
for( int i = 0; i < numOfVertices; ++i ) {
deleteAllAfter(vertices[i].list);
}
}
} //end of namespace graph
The Adj Matrix code
#ifndef ALTHGORITHM_GRAPH_ADJ_MATRIX_H
#define ALTHGORITHM_GRAPH_ADJ_MATRIX_H
#include <iostream>
#include <vector>
namespace graph_adj_matrix {
template<typename T>
class Graph {
int Num ;
enum visitedState {
NO_VISIT,
VISITING,
VISITED
};
struct vertex {
T data;
visitedState state;
};
std::vector<std::vector<int>> Matrix;
std::vector<vertex> matrix_list;
public:
Graph() = default;
Graph(std::vector<T> &);
~Graph();
void setMatrix(size_t index1, size_t index2);
void display();
};
template<typename T>
Graph<T>::Graph(std::vector<T> &values) :
Num(values.size())
,matrix_list(Num){
for (typename std::vector<T>::size_type i = 0; i < Num; ++i)
{
matrix_list[i].data = values[i];
matrix_list[i].state = NO_VISIT;
}
for (typename std::vector<T>::size_type i = 0; i < Num; ++i)
for (typename std::vector<T>::size_type j = 0; j < Num; ++j)
Matrix[i].push_back(0);
}
template<typename T>
void Graph<T>::setMatrix(size_t index1, size_t index2) {
for (size_t i = 0; i < Num; ++i) {
if (i == index1 || i == index2) {
for (size_t j = 0; j < Num; ++j) {
if (((i == index1) && (j == index2)) || ((i == index2) && (j == index1))) {
Matrix[i][j] = 1;
break;
}
}
break;
}
}
}
template<typename T>
void Graph<T>::display() {
for (size_t i = 0; i < Num; ++i) {
for (size_t j = 0; j < Num; j++)
std::cout << Matrix[i][j] << " ";
std::cout << std::endl;
}
}
template <typename T>
Graph<T>::~Graph() {}
}
#endif //ALTHGORITHM_GRAPH_ADJ_MATRIX_H
Cpp:
#include "Graph_Adj_List.h"
#include "Graph_Adj_Matrix.h"
int main() {
std::vector<std::string> myVec{"ABC","DEF","GHI","ZZZ"};
graph_adj_list::Graph<std::string> myGraph(myVec);
graph_adj_matrix::Graph<std::string> myGraph_matrix(myVec);
}
I have debugger the program
graph_adj_list::Graph<std::string> myGraph(myVec);
work well.
But the
graph_adj_matrix::Graph<std::string> myGraph_matrix(myVec);
stop at
#ifndef _LIBCPP_CXX03_LANG
template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
void
vector<_Tp, _Allocator>::push_back(value_type&& __x)
{
if (this->__end_ < this->__end_cap())
{
__RAII_IncreaseAnnotator __annotator(*this);
__alloc_traits::construct(this->__alloc(),
_VSTD::__to_raw_pointer(this->__end_),
_VSTD::move(__x));
__annotator.__done();
++this->__end_;
}
else
__push_back_slow_path(_VSTD::move(__x));
}
A function from vector header Row from 1635 to 1653.
Debugger report this
Exception = EXC_BAD_ACCESS (code=1, address=0x8)
this = {std::_11::vector<int,std::_1::allocator> * |0x0 } NULL
When I enter the body that sets the ```Matrix[i].push_back(0)''' It crashes the wrong condition.
The following is just an gues, after short playing around with your code:
Process finished with exit code 11
Probably could mean that your program encountered signal 11 (SIGSEGV, aka Segmentation fault)
My guess: you forgot to initialize Matrix, so Matrix[i].push_back(0); causes undefined behaviour and luckily resultet in a segmentation fault.
Edit: you can easily initialize the inner vectors with the vector constructor: std::vector<std::vector<int>>(Num, std::vector<int>(Num));. This will create a vector with Num copies of a vector with Num ints.
After having fixed the problem that #churill proposed:
I haven't compiled your code, but I think the problem lies on these lines:
Matrix[i][j] = 1;
In this case Matrix[i] is a vector<int>, but you never reserve capacity for it, so Matrix[i][j] is writing to protected / unallocated memory, causing the segfault.
Initialize your "internal" vectors (all Matrix[i]) with sufficient capacity and see if that resolves your segfault.
The code below a solution to the following requirement:
"Change the representation of Link and List from ยง27.9 without changing the user interface provided by the functions. Allocate Links in an array of Links and have the members: first, last, prev, and next be ints (indices into the array). " - Exercise 6 Chapter 27 - Programming: Principles and Practice Using C++ B. Stroustrup
The interface is inherited from an ordinary implementation of an Intrusive doubly linked list. I've added the bool array (and the associated functions) to keep track of memory:
#include <iostream>
struct Link
{
int next;
int prev;
};
//------------------------------------------------------------------------------------
struct List
{
Link** head;
int first; // points to the current first node
int last;
bool* available;
int list_size;
int get_index()
{
for (int i = 0; i < list_size; ++i)
{
if (available[i] == true)
{
available[i] = false;
return i;
}
}
throw std::bad_alloc("bla bla!\n");
}
List()
{
list_size = 30;
head = new Link*[list_size];
available = new bool[list_size];
first = -1;
last = -1;
for (int i = 0; i < list_size; ++i)
{
available[i] = true;
}
}
void List::push_back(Link* l)
{
if (l == nullptr)
{
throw std::invalid_argument("bla bla!\n");
}
int index = get_index();
head[index] = l;
if (last != -1)
{
head[last]->next = index;
head[index]->prev = last;
}
else
{
first = index;
head[index]->prev = -1;
}
last = index;
head[index]->next = -1;
}
void push_front(Link* l)
{
if (l == nullptr)
{
throw std::invalid_argument("bla bla\n");
}
int index = get_index();
head[index] = l;
if (first != -1)
{
head[first]->prev = index;
head[index]->next = first;
}
else
{
last = index;
head[index]->next = -1;
}
first = index;
head[index]->prev = -1;
}
// index = ptr - base
std::ptrdiff_t index_from_address(Link* l) { return l - head[0]; }
Link* front() const { return head[first]; }
};
//------------------------------------------------------------------------------------
int main()
{
List l;
for (int i = 0; i < 10; ++i)
{
l.push_back(new Link());
}
for (int i = 0; i < 10; ++i)
{
l.push_front(new Link());
}
std::cout <<"first = "<< l.first <<", index = " << l.index_from_address(l.front());
getchar();
}
Expected result:
first = 19, index = 19
Actual result:
first = 19, index = 194
Why?
l - head[0]
Here you compare the values of the two pointers. You let all pointers in the array be default initialized, so their values are indeterminate, and therefore the behaviour of accessing the values is undefined.
You probably intended index_from_address to find the index where a particular pointer object is stored - rather than the object that is pointed to, since the pointed to object is not in the array pointed by head. To do that, you must add a whole bunch of &:
Link*& front() const // return a reference to the pointer object, not a copy
// take a reference to the pointer as an argument, add const for good measure
std::ptrdiff_t index_from_address(Link*& l) const
// compare the addresses of the pointers, rather than values
{ return &l - &head[0]; }
I try to create a Graph class and want to print all Edges to the screen. But I have a problem iterating a 2d vector.
class Graph
{
public:
Graph(void);
~Graph(void);
vector<Node*> nodes;
void addNode(Node node);
void addDirectedEdge(Node &head,Node* tail,int cost);
void toSrceen();
};
class Node
{
public:
Node(char* name);
~Node(void);
char* name;
vector<Node*> children;
vector<int> costs;
};
void Graph::toSrceen()
{
for (vector<vector<Node*>>::iterator i = nodes.begin(); i != nodes.end();++i)
{
for (vector<Node*>::iterator j = i->begin(); j != i->end();++i)
{
cout << j->name;
}
}
}
There is a problem in the first for loop but i can not find the mistake...
It looks like the inner loop increments the wrong iterator. Probably needs to be:
for (vector<Node*>::iterator j = i->begin(); j != i->end();++j)
You're incrementing "i" each iteration of the second loop rather than j.
vector<vector<Node*>>::iterator i = nodes.begin()
if you look at the declaration of Graph::nodes, it's a vector<Node*>, not a vector<vector<Node*>>
the loop should probably be something like:
void Graph::toSrceen()
{
for (vector<Node*>::iterator i = nodes.begin(); i != nodes.end();++i)
{
Node* currNode = *i;
for (vector<Node*>::iterator j = currNode->children.begin(); j != currNode->children.end();++j)
{
cout << j->name;
}
}
}