Dynamic tree in C++ - c++

I'd like to make a tree which can have some childrens in every node, but i don't know number of them. Tree have to be coded in small memory using (no extra data) with constant time to every node. I tought that i will make class Tree with value and children property (value is int, and children is stack) and array of pointers to every node in that Tree. My problem is to make this array. How can i make it with no extra data (std::vector sometimes allocate more memory than it needs) and constant time to every cell?
Everything's ok, but i also need constant time to every node. I know how many nodes will be, but i dont know how to make array of every node. It should work something like:
array[n];
A_Node *array[0]= new A_Node(16);
A_Node *n = new A_Node(1);
array[0]->addChild(n);
array[1]=n;
Or:
*(array+1)=n;

This is a possible example. It is not a full example solution but I hope you get the point. The point is that you can have a double pointer to nodes, which is basically an array of pointers to nodes of the tree.
Then you can reallocate the size yourself and to however much you want whenever there is a need to. But std::vector already does that for you so there is no real reason not to use it unless you want to control everything yourself or experiment, or are writing something in C. In any case hope this helps.
#include <stdio.h>
#include <stdlib.h>
// The initial buffer length of a node's children
#define BUFFER_LENGTH 5
// How much to multiply with if an addition of a child goes over the buffer
#define MULTIPLIER 2
///Your node class
class A_Node
{
public:
A_Node(int value,unsigned int childrenN=0)
{
this->value = value;
this->childrenN = childrenN;
//allocate BUFFER_LENGTH children for the node at first or childrenN if the childrenN is not initially 0
if(childrenN != 0)
{
this->children = (A_Node**) malloc(sizeof(A_Node*)*childrenN);
this->bufferLength = childrenN;
}
else
{
this->children = (A_Node**) malloc(sizeof(A_Node*)*BUFFER_LENGTH);
this->bufferLength =BUFFER_LENGTH;
}
}
//in the destructor of a node it would need some special care
~A_Node()
{
//for every child call the destructor of each child
for(int i = 0; i < this->childrenN; i++)
{
delete this->children[i];
}
//and only then free the buffer of the pointers to the children
free(this->children);
}
//adds a child
void addChild(A_Node* child)
{
//reallocate if needed
if(childrenN >= this->bufferLength)
{
realloc(this->children,sizeof(A_Node*)*MULTIPLIER);
}
this->children[childrenN] = child;
this->childrenN++;
}
A_Node* getChild(unsigned int i)
{
if(i >= this->childrenN)
{
return 0;
}
return this->children[i];
}
void printValue()
{
printf("%d\n",this->value);
}
private:
int value;
unsigned int childrenN;
A_Node** children;
unsigned int bufferLength;
};
///Your tree class
class A_Tree
{
public:
//constructor
A_Tree(int rootValue)
{
root = new A_Node(rootValue);
}
//destructor
~A_Tree()
{
//recursively kills all the nodes due to the destructor of node
delete root;
}
//your root node
A_Node* root;
};
int main()
{
A_Tree tree(16);
tree.root->addChild(new A_Node(42));
tree.root->printValue();
(tree.root->getChild(0))->printValue();
return 0;
}

Just keep track of the memory yourself rather than using a vector:
class Node {
public:
// In the constructor, initialize your array of children to NULL
// and the size of your children array to zero
Node() : mChildren(NULL), mSize(0) {}
void AddChild(Node* newChild) {
// allocate space for your new array
Node** newArray = new Node*[mSize + 1];
// copy over nodes from old array to new array
for (int i = 0; i < mSize; i++) {
newArray[i] = mChildren[i];
}
// add in our new child to the end of the array
newArray[mSize++] = newChild;
// if there was an old array (null check) free the memory
if (mChildren) {
delete [] mChildren;
}
// set our children array equal to our new array
mChildren = newArray;
}
Node* AccessChild(size_t index) {
// make sure it's a valid index and then return
assert(index < mSize);
return mChildren[index];
}
private:
Node** mChildren;
int mSize;
};
This will have no extra space for extra nodes, but it will require the size of an int in order to keep track of how many nodes you are storing. I don't see any way you could do it without this or having a constant number of children.
Please note, vectors double in size each time they need to reallocate because this is more efficient. While the solution above will be more efficient memory-wise, it will hurt a lot performance wise because it will require an allocation for every child addition, which is going to take O(N) allocations to add N nodes.
The performance of a vector will be O(log(N)) allocations to add N nodes, but again this solution sounds like it has the memory efficiency you're looking for.

Related

Delete Zero in ArrayList in C++

Inside the ArrayList I'm trying to delete all possible 0's that are appended as input, but for now it only deletes just one 0, no matter where it is located. But seems like I can't delete more than one zero at the time. How can I fix this?
void AList::elimZeros(){
int i;
int curr = 0;
for(i=0; i < listSize; i++) {
if ( (listArray[i] != 0 ) && (curr<listSize) ){
listArray[curr] = listArray[i];
curr++;
}
else if (listArray[i] == 0 )
{
listArray[curr] = listArray[i+1];
listSize--;
curr++;
}
}
}
This is the class for the ADT
class AList : public List {
private:
ListItemType* listArray; // Array holding list elements
static const int DEFAULT_SIZE = 10; // Default size
int maxSize; // Maximum size of list
int listSize; // Current # of list items
int curr; // Position of current element
// Duplicates the size of the array pointed to by listArray
// and update the value of maxSize.
void resize();
public:
// Constructors
// Create a new list object with maximum size "size"
AList(int size = DEFAULT_SIZE) : listSize(0), curr(0) {
maxSize = size;
listArray = new ListItemType[size]; // Create listArray
}
~AList(); // destructor to remove array
This is the input I'm testing with:
int main() {
AList L(10);
AList L2(20);
L.append(10);
expect(L.to_string()=="<|10>");
L.append(20);
expect(L.to_string()=="<|10,20>");
L.append(30);
L.append(0);
L.append(40);
L.append(0);
L.append(0);
expect(L.to_string()=="<|10,20,30,0,40>");
L.elimZeros();
expect(L.to_string()=="<|10,20,30,40>");
assertionReport();
}
It'd be helpful if you posted the class code for AList. Think you confused Java's ArrayList type, but assuming you're using vectors you can always just do:
for (int i = 0; i < listSize; i++) {
if(listArray[i] == 0) listArray.erase(i);
}
EDIT: Assuming this is the template of for the AList class, then there is simply a remove() function. In terms of your code, there are two issues.
You reference listSize in the for loop, then decrement it inside of the loop. Each iteration evaluates the value separately so you're reducing the number of total loop iterations and stopping early.
The other thing is if the entry is zero you shouldn't increment curr and set listArray[curr] = listArray[i+1]. This is basically assuming the next entry will not be a zero. So if it is, then you're copying the element and moving to the next. Your if statement can be cleaned up with:
if (listArray[i] == 0) {
listSize--;
} else {
listArray[curr] = listArray[i];
curr++;
}

Not able to double the size of an array

I want to resize the array when the rehash function is called, by copying the values of initial dictionary into it and then at last redifining the newdictionary as dictionary
void rehash ()
{
int newsize=2*Size;
node **newdictionary;
newdictionary= new node*[newsize];
//Initialising the dictionary
for (int i = 0;i < newsize;i++)
{
newdictionary[i]->name = "";
newdictionary[i]->value = -1;
}
node **temp=dictionary;
delete [] dictionary;
dictionary=newdictionary;
SIZE=newsize;
for(int i=0;i<SIZE;i++)
{
if(temp[i]->value!= -1)
insertvalue(temp[i]->name,temp[i]->value);
}
delete [] temp;
};
Earlier I have defined insertvalue as:
void insertvalue (string filedata, int code)
{
// tableindex is the position where I want to insert the value
dictionary[tableindex]->name= filedata;
dictionary[tableindex]->value=code;
};
You didn't actually explain what problem(s) you're having, but your code has several issues:
void rehash ()
{
int newsize=2*Size;
node **newdictionary;
newdictionary= new node*[newsize];
At this point, newdictionary is simply an array of uninitialized pointers.
//Initialising the dictionary
for (int i = 0;i < newsize;i++)
{
newdictionary[i]->name = "";
newdictionary[i]->value = -1;
}
So the loop above is trying to access the members of node objects that don't yet exist.
node **temp=dictionary;
delete [] dictionary;
These two lines don't make sense. dictionary and temp point to the same memory. So when you delete dictinoary you've deleted the memory that temp is pointing to.
dictionary=newdictionary;
SIZE=newsize;
for(int i=0;i<SIZE;i++)
{
if(temp[i]->value!= -1)
insertvalue(temp[i]->name,temp[i]->value);
}
Even if you hadn't just deleted the memory out from under temp, you're now trying to access temp from 0 to the new size, not the old size. In other words, this would access temp beyond its bounds.
Those are the major problems that I've noticed in the code so far. You at least need to correct all of them before there's any hope of this working. You probably need to spend some time really stepping through your logic to ensure it makes sense in the end.

Implementation of stack in C++ without using <stack>

I want to make an implementation of stack, I found a working model on the internet, unfortunately it is based on the idea that I know the size of the stack I want to implement right away. What I want to do is be able to add segments to my stack as they are needed, because potential maximum amount of the slots required goes into 10s of thousands and from my understanding making the size set in stone (when all of it is not needed most of the time) is a huge waste of memory and loss of the execution speed of the program. I also do not want to use any complex prewritten functions in my implementation (the functions provided by STL or different libraries such as vector etc.) as I want to understand all of them more by trying to make them myself/with brief help.
struct variabl {
char *given_name;
double value;
};
variabl* variables[50000];
int c = 0;
int end_of_stack = 0;
class Stack
{
private:
int top, length;
char *z;
int index_struc = 0;
public:
Stack(int = 0);
~Stack();
char pop();
void push();
};
Stack::Stack(int size) /*
This is where the problem begins, I want to be able to allocate the size
dynamically.
*/
{
top = -1;
length = size;
z = new char[length];
}
void Stack::push()
{
++top;
z[top] = variables[index_struc]->value;
index_struc++;
}
char Stack::pop()
{
end_of_stack = 0;
if (z == 0 || top == -1)
{
end_of_stack = 1;
return NULL;
}
char top_stack = z[top];
top--;
length--;
return top_stack;
}
Stack::~Stack()
{
delete[] z;
}
I had somewhat of a idea, and tried doing
Stack stackk
//whenever I want to put another thing into stack
stackk.push = new char;
but then I didnt completely understand how will it work for my purpose, I don't think it will be fully accessible with the pop method etc because it will be a set of separate arrays/variables right? I want the implementation to remain reasonably simple so I can understand it.
Change your push function to take a parameter, rather than needing to reference variables.
To handle pushes, start with an initial length of your array z (and change z to a better variable name). When you are pushing a new value, check if the new value will mean that the size of your array is too small (by comparing length and top). If it will exceed the current size, allocate a bigger array and copy the values from z to the new array, free up z, and make z point to the new array.
Here you have a simple implementation without the need of reallocating arrays. It uses the auxiliary class Node, that holds a value, and a pointer to another Node (that is set to NULL to indicate the end of the stack).
main() tests the stack by reading commands of the form
p c: push c to the stack
g: print top of stack and pop
#include <cstdlib>
#include <iostream>
using namespace std;
class Node {
private:
char c;
Node *next;
public:
Node(char cc, Node *nnext){
c = cc;
next = nnext;
}
char getChar(){
return c;
}
Node *getNext(){
return next;
}
~Node(){}
};
class Stack {
private:
Node *start;
public:
Stack(){
start = NULL;
}
void push(char c){
start = new Node(c, start);
}
char pop(){
if(start == NULL){
//Handle error
cerr << "pop on empty stack" << endl;
exit(1);
}
else {
char r = (*start).getChar();
Node* newstart = (*start).getNext();
delete start;
start = newstart;
return r;
}
}
bool empty(){
return start == NULL;
}
};
int main(){
char c, k;
Stack st;
while(cin>>c){
switch(c){
case 'p':
cin >> k;
st.push(k);
break;
case 'g':
cout << st.pop()<<endl;
break;
}
}
return 0;
}

Constructor for LinkedList to receive an array C++

Attempting to write a constructor for LinkedList to be initialised with an array of integers.
The program would call linked(array); which will add all the values within the array in to a linkedlist.
LinkedList::LinkedList(int array[])
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < array.length(); ++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
the trouble is the array.length (coming from Java) and I don't think the array length can be obtained this way?
I would suggest you to use iterator idiom, and make the constructor a templated constructor as:
class LinkedList
{
//...
public:
template<typename FwdIterator>
LinkedList(FwdIterator begin, FwdIterator end)
{
for (;begin != end; ++begin)
{
//treat begin as pointer, and *begin as dereferenced object
}
}
//...
};
And then you can use it as:
int arr[] = {1,2,3,4,5,6,7,8,9,10};
LinkedList lnklist(arr, arr+10);
Not only that. If you've std::vector<int>, then you can also use it to construct the linked list, as:
std::vector<int> v;
//..
LinkedList lnklist(v.begin(), v.end());
So using iterator idiom gives you this much power and flexibility. :-)
As Nawaz explained, going with iterator solution is better. But if you want to go with array ( static one though), then compiler can automatically deduce the size for you.
template<size_t size>
LinkedList::LinkedList(int (&array)[size])
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < size++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
Can be called as shown below.
int arr[] = {1,2,3,4,5,6,7,8,9,10};
LinkedList lnklist(arr);
Like others have said, it is not only important but vital that you get a good introductory C++ book and read it from front to back, simultaneously trying to forget what you know about Java while in C++ mode. They are not remotely similar.
Now to your problem, it can be solved by using std::vector and using its size method:
// put this with the other includes for your file
#include <vector>
LinkedList::LinkedList(const std::vector<int>& array)
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < array.size(); ++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
If you don't want to use vector, you have to pass in the size of the array to the function:
LinkedList::LinkedList(int array[], int arrlen)
{
headPtr->setData(array[0]); //setData method stores the integer at position 0 inside headPtr
Node *currentPtr = headPtr;
for (int i = 0; i < arrlen; ++i) //for loop to add the integers to the next node
{
currentPtr->setNext(new Node(array[i])); //creates a new node with the integer value of array position i
}
}
But it is recommended to use the vector version.

array reallocation C++

Suppose you have an array, items, with capacity 5 and suppose also you have a count varaible that counts each entry added to the array. How would you realloacte the array? Using C++ syntax?
void BST::reallocate()
{
item *new_array = new item[size*2];
for ( int array_index = 0; array_index < size * 2; array_index++ )
{
if ( ! items[array_index].empty )
{
new_array[array_index].theData = items[array_index].theData;
new_array[array_index].empty = false;
}
}
maxSize += size;
delete [] items;
items = NULL;
items = new_array;
}
How do you reallocate an array?
BST ctor is below with the private items struct, just to eliminate any confusion.
BST::BST(int capacity) : items(new item[capacity]), Position(0),
leftChild(0), rightChild(0), maxSize(capacity)
{
}
this is in the BST header:
private:
int size;
int maxSize;
int Position;
int leftChild;
int rightChild;
struct item
{
bool empty;
data theData;
};
item *items;
The quesetion is that i seem to be having a hard time with the reallocation of my items array.
I would reallocate it in the form of a std::vector<item>, assuming that there is no overriding reason to use an array. That would avoid several problems completely.
Why are you doing this at all? Why do you think that:
std::vector<item> items;
won't work for you?
Your old array items has only size elements, so you need to change the upper limit in your for loop to size from size*2 when you're copying the old elements to the new array.
Maybe because size is not initialized. Also, you would need to make sure size is less than maxSize.