Inserting nodes in a Binary Tree recursively? - c++

I am trying to insert nodes in a binary tree recursively, but the code is only doing the root node and it's left and right children. I am trying to figure out how to get past that point.
I have already tried different implementations, using queues, doing level order insert. I believe the problem is due to the fact that in my main function I only call with root, and if that is the problem, how would I go about calling with the left and right childs.
Main Function:
int main() {
treenode* root = new treenode();
for(int a = 1; a < 15; a++) {
insert(root, a);
}
cout << "Height: " << height(root) << endl;
cout << "Printed Tree: " << endl;
for(int a = 0; a <= height(root); a++) {
printGivenLevel(root, a); //Print every level
cout << endl;
}
return 0;
}
Here is my insert function:
void insert(treenode*& node, int val) {
if(node == nullptr) {
node = new treenode(val);
return;
}else{
if(node->left == nullptr) {
insert(node->left, val);
}else{
insert(node->right, val);
}
}
}
A treenode has a value, a left child and right child:
struct treenode {
//The value of the node
int value;
//Pointers to the left and right children
treenode *left, *right;
//Constructor with values;
treenode(int val=0, treenode *l = nullptr, treenode *r = nullptr) : value(val), left(l), right(r) {};
};
I would expect the result to be something like so:
0
1 2
3 4 5 6
7 8 9 10 11 12 13 14
But my actual output is only:
0
1 2
Thanks in advance

... but the code is only doing the root node and it's left and right
children. I am trying to figure out how to get past that point.
I find no error in your treenode::insert, your problem might be in some other code you do not show. For example, you did not provide "height(root)" or "Printed Tree" info. I could not diagnose them.
I have provided some alternatives for various ideas. see "dump()" and "height()" and "size()".
Note: "dump()" is none of pre, in-, or post- order, because the sorted input creates unbalance tree displays (they are worst-case-unbalanced). I found this display the easiest to review.
Perhaps the following will help you diagnose your mistakes. Good luck.
Note the use of "if(false) cout << ...". These are diagnostic output which might provide some insights by enabling them, and / or adding such items to your code.
Did you try your debugger yet?
#include <chrono> // short form names----vvvvvvv
typedef std::chrono::high_resolution_clock HRClk_t; // std-chrono-hi-res-clk
typedef HRClk_t::time_point Time_t; // std-chrono-hi-res-clk-time-point
typedef std::chrono::nanoseconds NS_t; // std-chrono-nanoseconds
using namespace std::chrono_literals; // suffixes like 100ms, 2s, 30us
using std::chrono::duration_cast;
#include <iostream>
using std::cout, std::endl, std::flush;
#include <iomanip>
using std::setw;
namespace DTB
{
class treenode
{
friend class T920_t;
int value; //The value of the node
treenode *left, *right; //Pointers to the left and right children
//Constructor with values;
treenode(int val=0, treenode *l = nullptr, treenode *r = nullptr)
: value(val), left(l), right(r) { ctor('A'); };
void ctor(char kar) {
if (left) left->ctor(kar);
{
if(false) // diagnostic
cout << "\n ctor: " << " " << kar
<< " val: " << setw(3) << value << flush;
}
if(right) right->ctor(kar);
}
void insert ( treenode*& node, int val)
{
if(node == nullptr)
{
node = new treenode(val);
if (false) node->dump(); // diagnostic
return;
}
else
{
if(node->left == nullptr)
{
insert(node->left, val);
if (false) node->dump(); // diagnostic
}
else
{
insert(node->right, val);
if (false) node->dump(); // diaagnostic
}
}
}
int height(int lvl = 1)
{
static int maxHeight = 0;
if (left) left->height (lvl+1);
if(right) right->height (lvl+1);
if (lvl > maxHeight) maxHeight = lvl;
return maxHeight;
}
int size()
{
int count = 1; // this element
if (left) { count += left->size(); };
if(right) { count += right->size(); }
return count;
}
void dump(int lvl=0)
{
if (left) left->dump (lvl+1);
if(right) right->dump (lvl+1);
{
cout << "\n " // << lvl
<< setw(3*lvl) << ' '
<< value << flush;
}
}
}; // class treenode
typedef treenode Node_t; // shorter name for user-defined-type
class T920_t
{
public:
int operator()(int argc, char* argv[]) { return exec(argc, argv); }
private:
int exec(int , char** )
{
int retVal = 0;
Time_t start_ns = HRClk_t::now();
Node_t* root = new Node_t(); // 1st node
for(int v = 1; v < 21; ++v) { // 20 more
root->insert(root, v);
}
cout << "\n\n size : " << root->size() // element count
<< " maxHeight : " << root->height()
<< endl;
dumpAll(root);
for(int v = 1; v < 11; ++v) { // 10 more
root->insert(root, v);
}
cout << "\n\n size : " << root->size() // element count
<< " maxHeight : " << root->height()
<< endl;
dumpAll(root);
auto duration_ns = duration_cast<NS_t>(HRClk_t::now() - start_ns).count();
cout << "\n\n\n T920_t::exec() duration "
<< duration_ns << " ns "
<< " cpluplus vers : " << __cplusplus << std::endl;
return retVal;
}
void dumpAll (Node_t*& node)
{
cout << "\n dumpAll(): ";
node->dump();
cout << endl;
}
}; // class T920_t
} // namespace DTB
int main(int argc, char* argv[]) { return DTB::T920_t()(argc, argv); }
A partial output is:
size : 21 maxHeight : 11
dumpAll():
1
3
5
7
9
11
13
15
17
19
20
18
16
14
12
10
8
6
4
2
0
size : 31 maxHeight : 16
dumpAll():
1
3
...
10
8
6
4
2
0
T920_t::exec() duration 271095 ns cpluplus vers : 201703

Related

How to print the lead of A* algorithm

-I wrote a program to find the shortest path from a source node to a target node. Everything is fine, the program found the shortest path. But i have a problem, that is not able to print or get each node in the path. I tried many ways but no result. Hope anyone can help me, thanks everyone.
///////////////////////////////
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
typedef struct Node
{
int vertex;
int g;
int h;
int f;
Node* parent;
Node(int vertex)
{
this->vertex = vertex;
this->g = 0;
this->h = 0;
this->f = 0;
this->parent=NULL;
}
Node(int vertex,int g, int h, int f,Node*parent)
{
this->vertex = vertex;
this->g = g;
this->h = h;
this->f = f;
this->parent = parent;
}
}Node;
struct Edge
{
int source;
int dest;
int g;
int h;
};
struct comp
{
bool operator()(const Node* lhs, const Node* rhs) const {
return lhs->f < rhs->f;
}
};
std::vector<Node*>openList;
std::vector<Node*>closeList;
Node* startPos;
Node* endPos;
static const int WeightW = 10;
class Graph
{
public:
std::vector<std::vector<Edge>>adjlist;
Graph(const std::vector<Edge>& edges, int N)
{
adjlist.resize(N);
for (auto &edge:edges)
{
adjlist[edge.source].push_back(edge);
}
}
};
int isContains(std::vector<Node*>* Nodelist, int vertex);
void printPath(Node*node);
void findShortestPath(const Graph& grap,Node* start,Node* end, int N)
{
Node* node;
openList.push_back(start);
while (openList.size()>0)
{
node = openList[0];
closeList.push_back(node);
openList.erase(openList.begin());
std::cout << "start" << std::endl;
int u = node->vertex;
std::cout << "V: " << u << " g :" << node->g << std::endl;
std::cout << "continous" << std::endl;
for (auto v : grap.adjlist[u])
{
if (v.dest == end->vertex)
{
std::cout << "FindNode " << v.dest << std::endl;
printPath(node);
return;
}
if (isContains(&closeList, v.dest) == -1)
{
if (isContains(&openList, v.dest) == -1)
{
int vertex = v.dest;
std::cout <<"V: "<< vertex << std::endl;
int h = v.h;
int currentg = node->g + v.g;
int f = currentg + h;
std::cout <<"vertext: "<<vertex<< " h: " << h << " g: " << currentg << " f: " << f << std::endl;
Node* newNode = new Node(vertex, currentg, h, f,node->parent);
openList.push_back(newNode);
}
}
}
std::cout<<"Close: ";
for (size_t i = 0; i < closeList.size(); i++)
{
std::cout << closeList[i]->vertex << " ";
}
std::cout << std::endl;
sort(openList.begin(), openList.end(),comp());
std::cout << "Open: ";
for (size_t i = 0; i < openList.size(); i++)
{
std::cout << openList[i]->vertex << " ";
}
std::cout << std::endl;
std::cout << "end" << std::endl;
std::cout << std::endl;
}
}
void printPath(Node* node)
{
std::cout << std::endl;
if (node->parent != NULL)
printPath(node->parent);
std::cout << node->vertex << " ";
}
int isContains(std::vector<Node*>* Nodelist,int vertex)
{
for (int i = 0; i < Nodelist->size(); i++)
{
if (Nodelist->at(i)->vertex== vertex)
{
return i;
}
}
return -1;
}
int main()
{
//{Node,Node,G,H}
//Firt Node
//second Node
//G is the movement cost to move from the starting point to a given square on the grid
// following the path generated to get there
//H is the estimated movement cost to move from that given square on the grid to the final destination
std::vector<Edge>edges =
{
{0,1,5,17},
{0,2,5,13},
{1,0,5,16},
{1,3,3,16},
{1,2,4,13},
{2,0,5,16},
{2,1,4,17},
{2,3,7,16},
{2,4,7,16},
{2,7,8,11},
{3,2,7,13},
{3,7,11,11},
{3,10,16,4},
{3,11,13,7},
{3,12,14,10},
{4,2,7,13},
{4,5,4,20},
{4,7,5,11},
{5,4,4,16},
{5,6,9,17},
{6,5,9,20},
{6,13,12,7},
{7,3,11,16},
{7,4,5,16},
{7,8,3,10},
{8,7,3,11},
{8,9,4,8},
{9,8,4,10},
{9,13,3,7},
{9,15,8,0},
{10,3,16,16},
{10,11,5,7},
{10,13,7,7},
{10,15,4,0},
{11,3,13,16},
{11,10,5,4},
{11,12,9,10},
{11,14,4,5},
{12,3,14,16},
{12,11,9,7},
{12,14,5,5},
{13,9,3,8},
{13,10,7,4},
{13,15,7,0},
{14,11,4,7},
{14,12,5,10},
{15,9,8,8},
{15,10,4,4},
{15,13,7,7},
};
int n = edges.size();
Graph grap(edges, n);
//std::cout << h << std::endl;
Node* start = new Node(0);
Node* end = new Node(15);
findShortestPath(grap, start, end, n);
//Astar astar;
//Node* startPos = new Node(5, 1);
//Node* endPos = new Node(1, 8);
//astar.printMap();
//astar.search(startPos, endPos);
//cout << endl;
//astar.printMap();
system("pause");
return 0;
}
Your program doesn't find the shortest path. It gives the wrong output. (you're on the right track though)
I will assume you are trying to find the shortest path by using BFS. Let's take a look at line 113:
sort(openList.begin(), openList.end(),comp());
Here you're sorting your BFS queue (vector in your case) and thus destroying the right order.
Delete that line.
Congrats, now your program finds the shortest path!
Next, as I understand, for each node you branch into, you remember which node you came from in order to backtrack the path once you reach the destination or final node.
In line 102:
Node* newNode = new Node(vertex, currentg, h, f,node->parent);
you are assigning the new node's grandparent instead of parent. Change that line to
Node* newNode = new Node(vertex, currentg, h, f,node);
Now your printPath function works properly and prints the right path. (just add the target node)
Anyways, your code has a lot of space for improvements. Check out other implementations online and try to see if you can code it as short and clean for practice. Good luck!

How to "print list from tail to head" recursively?

I'm trying to print each node in a linked list from tail to head using recursion. But why I can't use the highlighting code to realize a recursion?
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
if(!head)
{
vector<int> a(0);
return a;
}
else if(!head -> next)
{
vector<int> a(1, head -> val);
return a;
}
else
/*
return printListFromTailToHead(head -> next).push_back(head -> val);
*/
}
};
If you want to print, then print - don't build a vector.
void printListFromTailToHead(ListNode* head)
{
if (head)
{
printListFromTailToHead(head->next);
std::cout << head->val << '\n';
}
}
If you actually don't want to print anything but produce a vector, you need to rearrange the code a little bit, because push_back does not return anything:
vector<int> reverse_list(ListNode* head)
{
if (!head)
{
return vector<int>{};
}
else // You don't need a special case for a one-element list.
{
vector<int> ls = reverse_list(head->next);
ls.push_back(head->val);
return ls;
}
}
Your function outputs nothing. And it is a bad idea to use a vector to output recursively a list.
The function can look for example the following way as it is shown in a demonstrative program below.
#include <iostream>
struct ListNode
{
int value;
ListNode *next;
};
void push_front( ListNode * &head, int value )
{
head = new ListNode { value, head };
}
std::ostream & printListFromHeadToTail( ListNode * &head, std::ostream &os = std::cout )
{
return head == nullptr ? os
: ( os << head->value << ' ', printListFromHeadToTail( head->next, os ) );
}
std::ostream & printListFromTailToHead( ListNode * &head, std::ostream &os = std::cout )
{
return head == nullptr ? os
: ( printListFromTailToHead( head->next, os ), os << head->value << ' ' );
}
int main()
{
const int N = 10;
ListNode *head = nullptr;
for ( int i = 0; i < N; i++ ) push_front( head, i );
printListFromHeadToTail( head ) << '\n';
printListFromTailToHead( head ) << '\n';
return 0;
}
Its output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
Check out this solution, maybe isn't the better way to do it, but you maybe can take the idea. The thing is, you do not need return an array, also I did not get it why are you returning an vector, you could just call the function again and then print it like the code bellow.
#include <iostream>
using namespace std;
class ListNode {
public:
ListNode *next;
int value;
ListNode() {
this->next = NULL;
this->value = 0;
}
ListNode(int _v) {
this->next = NULL;
this->value = _v;
}
};
void printListNodeFromTailToHead(ListNode *node) {
// If the current node is null will
// exit the recursive function
if (node == NULL) return ;
// Else will call the function again with next ListNode
// and print the current value
printListNodeFromTailToHead(node->next);
cout << node->value << endl;
}
int main() {
ListNode *a = new ListNode(1);
ListNode *tmp = a;
for (int i = 2; i < 10; i++) {
a->next = new ListNode(i);
a = a->next;
}
printListNodeFromTailToHead(tmp);
return 0;
}
I'm trying to print each node in a linked list from tail to head using
recursion
Because you provide no info about your list, here I will show you a simple implementation of your desired function(s) using a "std::list". Note that the recursion I provide has no function parameters, no global scope vars, and no static vars (and I use cout, not print).
Also, I use a class form known as a Functor. I recommend them for encapsulating 'small' function(s). Please review literature on functors ... I consider them 'simpler' than the typical class.
#include <iostream>
using std::cout, std::cerr, std::endl, std::flush; // c++17
using std::ostream;
#include <list>
using std::list;
#include <string>
using std::string, std::to_string;
// typedefs are often simpler to read
// user typedefs ---------------vvvvvvvvvvv
typedef list<string> StrList_t;
typedef list<string>::iterator StrListIt_t;
// Functor
class F820_Recursive_t
{
// data attributes of class instance are not global nor static vars
StrList_t m_strList;
StrListIt_t m_it;
public:
int operator()() { return exec(); } // Functor entry
private:
int exec() // builds and modifies a std::list<string>
{
// example: using initializer list syntax
m_strList = StrList_t { "111", "222", "333", "444", "555", "666", "777", "888" };
recurseAndReportSize();
// example: appending to existing list
for (int i=301; i<309; ++i) {
string s = "S" + to_string(i);
m_strList.push_back (s);
}
recurseAndReportSize();
cout << "\n version cplusplus: " << __cplusplus << "\n\n" << endl;
return 0;
}
void recurseAndReportSize()
{
if (0 == m_strList.size()) {
cout << "\n empty list" << flush;
return;
}
cout << "\n\n recurse over list to count elements ... " << flush;
m_it = m_strList.begin(); // head to tail
uint count = recurseCount();
// report
cout << count << " elements" << endl;
// report list contents head to tail
m_it = m_strList.begin();
cout << "\n Head to Tail recursive content report "
<< "\n [" << coutListFromHeadToTail() << "]" << endl;
// report list contents tail to head
m_it = m_strList.end(); m_it--;
cout << "\n Tail to Head recursive content report: "
<< "\n [" << coutListFromTailToHead() << "]" << endl;
}
// recurse with no parameters, no static vars, no global vars
uint recurseCount( )
{ // --^-- no parameters
if (m_it == m_strList.end()) // RTC (recursion termination clause)
return 0;
m_it++; // step to next element
return (1 + recurseCount()); // tail recursion
}
// recurse with no parameters, no static vars, no global vars
string coutListFromHeadToTail ( )
{ // --^-- no parameters
cout << *m_it++;
if (m_it == m_strList.end()) // RTC (recursion termination clause)
return "";
cout << ", ";
return coutListFromHeadToTail(); // tail recursion
}
// recurse with no parameters, no static vars, no global vars
string coutListFromTailToHead ( )
{ // --^-- no parameters
if (m_it == m_strList.begin()) {
cout << *m_it;
return "";
}
cout << *m_it << ", ";
m_it--;
return coutListFromTailToHead(); // tail recursion
}
}; // class F820_Recursion_t
int main(int, char**) { return F820_Recursive_t()(); }
Output on my Lubuntu 19.04, g++ v8.3
recurse over list to count elements ... 8 elements
Head to Tail recursive content report
[111, 222, 333, 444, 555, 666, 777, 888]
Tail to Head recursive content report:
[888, 777, 666, 555, 444, 333, 222, 111]
recurse over list to count elements ... 16 elements
Head to Tail recursive content report
[111, 222, 333, 444, 555, 666, 777, 888, S301, S302, S303, S304, S305, S306, S307, S308]
Tail to Head recursive content report:
[S308, S307, S306, S305, S304, S303, S302, S301, 888, 777, 666, 555, 444, 333, 222, 111]
version cplusplus: 201703

Bus error c++ Run correctly with small array, run time error with big array

Can anyone help me? The printAll(), listprintAll() and sizeLL() work correctly when hashSize is small but didn't work with big number, like number 9973.
printAll() and hashStats() are both method in Class Table, printALL() calls listprintAll() and hashStats() calls sizeLL() from another Structure.
All functions work correctly with give small hashSize.
Sorry about the pic and confused. first time here.. I'm using MacBook to do this work.
In list.h
struct Node{
string key;
int value;
Node *next;
Node(const string &theKey, int theValue);
Node(const string &theKey, int theValue, Node *n);
};
typedef Node * ListType;
In Table.h
class Table {
public:
static const int HASH_SIZE = 9973; // a prime number
// create an empty table, i.e., one where numEntries() is 0
// (Underlying hash table is HASH_SIZE.)
Table();
// create an empty table, i.e., one where numEntries() is 0
// such that the underlying hash table is hSize
Table(unsigned int hSize);
unsigned int hashSize; // size of the hash table
ListType * data; // (used in hashCode method above)
}
In list.cpp
void listprintAll(ListType list){
if(list ==NULL) {
cout << "[ ]" <<endl;
return;}
else{
Node * p=list;
while(p!= NULL){
cout << p->key << " " << p->value << ",";
p=p->next;
}
cout <<endl;
return;
}
}
int sizeLL(ListType list){
if(list ==NULL) {
return 0;}
else{
int count=0;
Node * p=list;
while(p!= NULL){
p=p->next;
count++;
}
return count;
}
In Table.cpp
Table::Table() {
hashSize=HASH_SIZE;
data = new ListType[hashSize];
}
Table::Table(unsigned int hSize) {
hashSize=hSize;
data = new ListType[hashSize];
}
void Table::printAll() const {
for(int i=0;i<hashSize;i++){
listprintAll(data[i]);
}
}
void Table::hashStats(ostream &out) const {
out << "number of buckets: "<< hashSize <<endl;
int number = numEntriesOfTable();
out << "number of entries: "<< number <<endl;
int countN0=0;
int longest=0;
int temp;
if(number!=0){
for(int i=0;i<hashSize;i++){
temp=sizeLL(data[i]);
if(temp!=0){
countN0++;
if(temp > longest){
longest=temp;
}
}
}
}
out << "number of non-empty buckets: "<< countN0 << endl;
out << "longest chain : "<< longest << endl;
}
You're allocating memory for data in your constructors but not initializing it. This leaves all your pointers with indeterminate values in them, which could be 0/NULL or could be some other random pointer value. When you try to dereference these you get the crash.
You'll want to zero out your allocated memory in the constructor, using a loop, memset, or something along those lines.

Using C++ to match parentheses, braces and brackets

We're supposed to implement a program to check whether the braces, brackets and parens in a given expression all match using a stack structure in C++ for my CS class. Unfortunately, I'm kinda stuck on this one, since I keeps telling me something doesn't match, even when it most decidedly does.
Here's what I got so far:
#include <stdlib.h>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
struct cell {int value; cell* next; };
cell* top;
int numElem;
void init()
{
top = NULL;
numElem = 0;
}
int pop()
{
int res;
if (top != NULL)
{
res = top -> value;
top = top -> next;
numElem--;
} else {
cout << "FAIL: Stack empty!\n";
res = -1;
}
return res;
}
void push(int element)
{
cell* cat = new cell;
cat -> value = element;
cat -> next = top;
top = cat;
}
void match(char expr[])
{
bool pass = true;
char expected;
char encountered;
char closing;
for (int i=0; pass && (i<strlen(expr)); i++)
{
if ((i==40)||(i==91)||(i==123))
push(i);
else
{
if (i==41)
expected = 40;
if (i==93)
expected = 91;
if (i==125)
expected = 123;
encountered = pop();
if (expected != encountered)
closing = i;
pass = false;
}
}
if (pass)
cout << "Parentheses match OK!\n";
else
cout << encountered << " has opened, but closing " << closing;
cout << " encountered!\nParentheses do not match\n";
}
int main(int argc, char * argv[])
{
init();
match(argv[1]);
return 0;
}
Since the stack framework existed from a previous exercise and worked fine there, I'm strongly assuming whatever error there is should be in void match
else
cout << encountered << " has opened, but closing " << closing;
cout << " encountered!\nParentheses do not match\n";
The second line always prints. It should be
else
{
cout << encountered << " has opened, but closing " << closing;
cout << " encountered!\nParentheses do not match\n";
}
Also
if (expected != encountered)
closing = i;
pass = false;
should also be
if (expected != encountered)
{
closing = i;
pass = false;
}
Do you come from python? Indentation doesn't affect logic in C++, it just affects readability.
In your match function you should test characters, not their indices:
void match(char expr[])
{
...
for (int i=0; pass && (i<strlen(expr)); i++)
{
char c = expr[i]; // use this c instead of i below!!!!!!!
if ((c==40)||(c==91)||(c==123))
push(c);
else
{
if (c==41)
expected = 40;
if (c==93)
expected = 91;
if (c==125)
...
Also you did not update counter in your push:
void push(int element)
{
...
++numElems; // Was missing!!!!
}

linux x64 c++ allocates way too much memory for a linked list; why?

i will be using linked list example code seen here on stackoverflow to illustrate the problem.
my c++ written progam (x64) contains this linked list code :
old code snippets deleted; im sorry if comments doesnot make sense anymore.
added fully working code to show what my problem is.
compile : g++ linkedlist.cpp -o linked-list
#include <cstdlib>
#include <iostream>
using namespace std;
struct node
{
public :
unsigned int part1; // 4 bytes
unsigned int part2; // 4 bytes
node *next; //pointer, 8 bytes on 64 bit system
unsigned int read_part1();
};
struct LinkedList
{
public:
LinkedList();
void insert(unsigned int data[], unsigned int data1);
bool isEmpty() const;
node* head;
};
unsigned int node::read_part1() {
return part1;
}
LinkedList::LinkedList():
head(NULL)
{
}
bool LinkedList::isEmpty() const
{
return (head == NULL);
}
void LinkedList::insert(unsigned int data[], unsigned int data1)
{
node* oldHead = head;
node* newHead = new node();
newHead->part1 = data[0];
newHead->part2 = data1;
newHead->next = oldHead;
head = newHead;
}
unsigned int allocations = 300000000;
unsigned int index_size = 430000000;//index of lists, 430m,.
//will be creatad on heap
LinkedList *list = NULL;
int main(int argc, char *argv[])
{
LinkedList list_instance;
cout << "1 LinkedList instance takes [" << sizeof(list_instance) << "] bytes in memory!"<< endl;
node node_instance;
cout << "1 node instance takes [" << sizeof(node_instance) <<"] bytes in memory !"<< endl;
try{
list = new LinkedList[index_size];
}
catch(std::bad_alloc) {
cout << "Error allocating memory" << endl;
return 0;
//reboot code
}
unsigned int some_data[] = {00, 01};
unsigned int index;
LinkedList *list_instance2 = NULL;
cout << "Allocating ..." << endl;
for (int i=0; i<allocations; i++)
{
index = rand();
unsigned short inde = (unsigned short)index;
list_instance2 = &list[inde];
list_instance2->insert(some_data, some_data[1]);
}
unsigned long sk = ((allocations * sizeof(node_instance) + index_size*sizeof(list_instance))) / (1024*1024*1024);
cout << "This process *should* consume around " << sk <<" GBytes of memory, but does it ?"<< endl;
cout << "Allocating done, *check the process size* and press any number key + ENTER to exit ..." << endl;
int u=0;
cin >> u;
return 0;
}
compile it, run it and see if your process size even remotely matches whats expected.
if not - where is the problem ?
oh, and i run it on 64 bit slackware 13.37 with a unmodified default kernel.
On my box, with slightly modified source (see below with notes)
it uses 1243 MiB rather than the 'expected' 785 MiB using the standard library heap routines
it uses 791 MiB when using Google's tcmalloc
it uses 840 MiB when using Boost Object Pool to allocate nodes (with standard library heap or tcmalloc)
The overhead is very clearly in the implementation of the heap routines.
Here's the code:
Note the use of new (nothrow) there.
Also, the baseline measurement at the start (I used pmap $(pgrep test) | tail on linux)
Note the choice in insert:
void LinkedList::insert(unsigned int data[], unsigned int data1)
{
#if 1
head = new node { data[0], data1, head };
#else
static boost::object_pool<node> node_pool;
node* add = node_pool.malloc();
*add = node { data[0], data1, head };
head = add;
#endif
}
Change #if 1 to #if 0 to use the Boost Object Pool
There was a strangeness in the node allocation loop
index = rand();
unsigned short inde = (unsigned short)index;
list_instance2 = &list[inde];
list_instance2->insert(some_data, some_data[1]);
I changed it to what you probably intended:
list[rand() % index_size].insert(some_data, some_data[1]);
#include <stdlib.h>
#include <iostream>
#include <boost/pool/object_pool.hpp>
using namespace std;
struct node
{
unsigned int part1; // 4 bytes
unsigned int part2; // 4 bytes
node *next; //pointer, 8 bytes on 64 bit system
};
struct LinkedList
{
public:
LinkedList();
void insert(unsigned int data[], unsigned int data1);
bool isEmpty() const;
node* head;
};
LinkedList::LinkedList():
head(NULL)
{
}
bool LinkedList::isEmpty() const
{
return (head == NULL);
}
void LinkedList::insert(unsigned int data[], unsigned int data1)
{
#if 1
head = new node { data[0], data1, head };
#else
static boost::object_pool<node> node_pool;
node* add = node_pool.malloc();
*add = node { data[0], data1, head };
head = add;
#endif
}
const unsigned int allocations = 30000000;
const unsigned int index_size = 43000000;//index of lists
//will be creatad on heap
LinkedList *list = NULL;
int main(int argc, char *argv[])
{
LinkedList list_instance;
cout << "1 LinkedList instance takes [" << sizeof(list_instance) << "] bytes in memory!"<< endl;
node node_instance;
cout << "1 node instance takes [" << sizeof(node_instance) <<"] bytes in memory !"<< endl;
cout << "Before dynamic allocations: *check the baseline process size* and press ENTER to start allocating ..." << endl;
std::string s;
std::getline(std::cin, s);
list = new (nothrow) LinkedList[index_size];
if (!list)
{
cout << "Error allocating memory" << endl;
return 1;
}
unsigned int some_data[] = {00, 01};
cout << "Allocating nodes ..." << endl;
for (unsigned int i=0; i<allocations; i++)
{
list[rand() % index_size].insert(some_data, some_data[1]);
}
unsigned long sk = ((allocations * sizeof(node_instance) + index_size*sizeof(list_instance))) >> 20;
cout << "This process *should* consume around " << sk <<" MiB of memory, but does it ?"<< endl;
cout << "Allocating done, *check the process size* and press ENTER to exit ..." << endl;
std::getline(std::cin, s);
return 0;
}