My preorder method don't work from main, but array elem has been formed rightly (I checked it with printing every step). All functions/methods used in definition work correctly. I think the problem occurs because of line "return elem;". Can anyone suggest any idea, it's too important.
T* TreeNode<T>::preorder()const
{
T* elem = new T[elCount(left)+elCount(right)+1];
elem[0] = data;
TreeNode<T>* curr = left;
Stack<TreeNode<T>*> st;
if (right) {
st.push(right);
}
int i = 1;
while (curr) {
elem[i++] = curr->getData();
//std::cout << elem[i - 1];
if (curr->getRight())
st.push(curr->getRight());
curr = curr->getLeft();
if (!curr)
{
curr = st.getTop();
st.pop();
} }
return elem;
}
It's a bit difficult to see exactly what you're trying to do as it wasn't specified, but it seems that you're trying to grab all the data from your binary tree. This GFG article does a really simple explanation and breakdown of how to transverse a binary tree. Obviously your nodes are more complicated, but the general logic is the same. I'd ask yourself as to whether the preorder() function really needs to be part of the tree node class and if a separate function wouldn't be a bit more useful. I'd also consider using a std::vector rather than the carray you're currently using. If you need the fixed size, std::array would probably also work better.
To show how you could possibly rewrite your code you can try something like
std::vector<int> vect;
template<class T>
void preorder(const TreeNode<T>& node, vector<T>& elem) {
if(!node.getData()) {
return;
}
elem.push(node.getData());
if(node.getLeft()) {
preorder(node.getLeft());
}
if(node.getRight()) {
preorder(node.getRight());
}
}
This isn't perfect as I wrote this off the top of my head, but it should provide an easy groundwork for traversing the binary tree and pulling out all the data. A little bit of recursion should make it a lot easier.
Related
I am moderately new to coding so I would appreciate some help especially when I have no one to ask and only have books and YouTube to consult.
This is my code for a function that makes a binary tree in level order from the given string. I did a lot of trial and error to figure this out.
My question is why does this code only work when the queue contains addresses of pointers i.e. queue is queue<TreeNode**>q and not when it is made up of pointers i.e. queue<TreeNode*>q.
NOTE: While using queue<TreeNode*>q I will obviously use the necessary practices of storing root in it instead of &root.
I feel like the second case (queue<TreeNode*>q) should also work since it is pointers and not the actual object being stored. So it should work with the same logic of storing left and right.
TreeNode* deserialize(string data) {
if(data=="#,"){return {};}
stringstream a(data);
string temp;
vector<string>token;
while(getline(a, temp, ','))
{token.push_back(temp);}
TreeNode* root=NULL;
queue<TreeNode**>q;
q.push(&root);
for(int i=0;i<token.size();i++)
{
if(token[i]!="#")
{
(*q.front())=new TreeNode(stoi(token[i]));
q.push(&(*q.front())->left);
q.push(&(*q.front())->right);
}
q.pop();
}
return root;
}
};
With the current code and using queue<TreeNode**>q;, what happens essentially is that I am taking a number and storing it in the TreeNode and then pushing that TreeNodes left and right child in the queue. The end result is a connected tree.
When done with queue<TreeNode*>q, the same thing DOES NOT result in the nodes connecting.
what you have done is, you are pushing the address of root in the queue in line q.push(&root) ,instead of only root. That's why it requires double pointer. Refer to the code below:
TreeNode* deserialize(string data) {
if(data=="#,"){return {};}
stringstream a(data);
string temp;
vector<string>token;
while(getline(a, temp, ','))
{token.push_back(temp);}
TreeNode* root=NULL;
queue<TreeNode*>q;
q.push(root);
for(int i=0;i<token.size();i++)
{
if(token[i]!="#")
{
(q.front())=new TreeNode(stoi(token[i]));
q.push(q.front()->left);
q.push(q.front()->right);
}
q.pop();
}
return root;
}
};
Change these lines also:
if(token[i]!="#")
{
(*q.front())=new TreeNode(stoi(token[i]));
q.push(&(*q.front())->left);
q.push(&(*q.front())->right);
}
q.pop();
Refer the code above
So I recently came across a data structure roughly like this:
template<class T>
struct Node {
size_t m_next;
size_t m_prev;
T m_key;
}
template<class T, size_t N>
struct DS {
Node<T> m_elements[N];
size_t m_head;
size_t m_tail;
}
I simplified a bit, just to keep this brief: I don't do error handling when DS gets too full. Normally N is large enough that this isn't a concern.
One note is T must have some way of representing "no value"; why this is needed can be seen below. (I'll refer to this value as TOMBSTONE below.)
The API for this data structure is roughly the same as for a linked list, but it performs much better because everything fits nicely in the cache.
The actual implementation is different from a linked list in that it doesn't need to allocate any new memory for new nodes. For example, pushing to the back of DS is roughly like this:
void DS::push_back(T t) {
size_t attempt = 0;
size_t i = hash(t, attempt++);
while (true) {
if (m_elements[i] == TOMBSTONE) {
m_elements[m_tail].m_next = i;
m_elements[i] = Node(N, m_tail, t);
m_tail = i;
break;
}
i = hash(t, attempt++);
}
}
where hash(T t, size_t attempt) finds places to try to insert new elements. (This is so there's nice spread, rather than clumping everything at the start.)
I hesitate to call this a linked list because of the vast performance and implementation differences from a normal linked list. I also want to point out that this question is not about when to use what data-structures, or if the above data-structure is good/fast/safe/whatever. This data-structure works quite well for us in the very specific situation we use it in.
Is there any name for this particular implementation/data-structure?
It is linked list. It's mentioned on Wikipedia as "Linked list using arrays of nodes"
It's a double-linked linked list, implemented with a C-style array.
So I have this group project that's supposed to take in a text file, chop it up into species and sub species and that sort of thing. I've finished the chopping and the tree structure but I'm having a hard time getting my BuildGraph() to work. I've narrowed it down to the findNode() function that right now looks like
EDIT: comments, Also this is my first time posting so sorry if it's ugly.
I had both of these changes in a different version but ended up getting rid of them somewhere?
Node* findNode(std::string data, Node* head){
if (head == NULL){
return NULL;
}
else if(head->data == data){
return head;
} else {
if(head->children[0]!=NULL){
for(int i = 0; i<head->children.size();i++){
return findNode(data, head->children.at(i));
}
}
}
My Node structure looks like this...
public:
std::string data;
std::vector <Node*> children;
Node(std::string data){
this->data=data;
}
I'm pretty sure that the problem that I'm running into is something about the recursive call is going deeper rather than expanding somehow causing a segfault.
Can someone tell me if what I'm looking to do is possible?
You have 2 problems:
if(head->children[0]!=NULL){
You access children[0] but you don't check if children is empty. I'm fairly sure this causes your SegFault.
return findNode(data, head->children.at(i));
You need to check if this is null before returning. In case it's null you want to check the other children.
Also pass const std::string& data so that you don't copy the string at every call.
Please have a look at the following diagram
This is how I implemented it
template <typename T>
class LinkedList
{
struct Link {
T data;
struct Link *next;
public:
T *first;
};
LinkedList::LinkedList(void)
{
first = 0;
}
LinkedList::~LinkedList(void)
{
}
bool LinkedList::IsEmpty()
{
return (first==0);
}
void LinkedList::Insert(Link *newLink)
{
newLink->next = first;
first = newLink;
}
void LinkedList::Display()
{
Link *current = first;
while(current!=0)
{
current->Display();
current = current->next;
}
}
T *LinkedList::Find(int value)
{
Link *current = first;
while(current->GetData()!=value)
{
if(current->next==0)
{
return 0;
}
else
{
current = current->next;
}
}
return current;
}
T *LinkedList::Delete(const int id)
{
Link *current = first;
Link *previous = first;
while(current->GetData()!=id)
{
if(current->next==0)
{
return 0;
}
else
{
previous = current;
current = current->next;
}
}
if(current==first)
{
first = first->next;
}
else
{
previous->next = current->next;
}
return current;
}
};
I do not feel comfortable about my implementation. Specially, I have no idea about what to do inside the insert() method, using T type.
Following is the diagram for another class, it's next pointer is Weapons represent links within a linked list. I doubted whether this is the "Link" class as well. Next is a pointer to the next weapon in the list. I posted it here if it affects the above code.
How to deal inside the insert() method? Apart from that, is my Linked List correct? First time with templates for Linked Lists anyway. Please help!
NOTE: BUILT IN DATA STRUCTURES ARE NOT ALLOWED. THAT IS WHY I POSTED THE DIAGRAM OF CLASSES. IF I NEED BUILT IN DATASTRUCTURE SUPPORT, THEN I AM NOT ASKING HOW TO BUILD THE CODE BY MY SELF.
The question I would rather answer:
My particular problem / exercise is ....
How do I solve my problem using std::list or some other standard library container, which will probably use less lines, be easier to understand, be more efficient and help me achieve more as a programmer?
The unspoken question I'm trying hard not to answer:
What is wrong with my code?
The question I think you are actually asking:
How can I fix my insert() method?
Answer to the last question only:
It seems like you are trying to append the new link onto the front of the list. Conceptually I would be appending it to the back of the list, but hey, each to his own.
The rub is in the types: Inside your class, the type of your first is T *, where T might be some custom class that implements GetData(). So first points to a T, it should probably point to a Link which points to a T.
Then your insert() method makes a bit more sense.
Still, it is really hard to know if your code is correct without a compliable piece of code, which has a defined predicted output. At least with the standard library you can always assume that if there is a problem, it is not in the linked list implementation.
Do you need to do it yourself because it is homework?
So i want to make a code, that creates a binary tree, that holds data, for example ints like 1,6,2,10,8 and on pop i get the biggest number, and after that it gets deleted from the tree, and on push i can insert a new element. And this should be in a template so i can easy change the data type i want to hold in the tree. Now i got the tree so far, without template it is working fine thought, i can add items, and i can print them, but when i try to put it in a template, i get the following error: use of class template requires template argument list . What could be the problem? Maybe i am doing it totally wrong. Any suggestions are welcome.
This was my first question it got fixed by avakar ty. (i will post the code at the end of my question)
I just read trough the project request , and its like, i have to make this thing i above in the first part of question described, but its like the binary tree should represent a priority queue. And that is why in the request is written that i have to use push to put a new element in the tree by priority order and with pop i will get the element with the highest priority and then that element will be deleted. So how could i use my Tree as a Priority queue, or is he already one(i think not but who knew)? I hope i could explain it.
And here is the code as promised:
#include <iostream>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = NULL;
rChildptr = NULL;
}
};
private:
Node* root;
void Insert(T newData, Node* &theRoot)
{
if(theRoot == NULL)
{
theRoot = new Node(newData);
return;
}
if(newData < theRoot->data)
Insert(newData, theRoot->lChildptr);
else
Insert(newData, theRoot->rChildptr);;
}
void PrintTree(Node* theRoot)
{
if(theRoot != NULL)
{
PrintTree(theRoot->lChildptr);
cout<< theRoot->data<<" ";;
PrintTree(theRoot->rChildptr);
}
}
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T newData)
{
Insert(newData, root);
}
void PrintTree()
{
PrintTree(root);
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(1);
myBT->AddItem(7);
myBT->AddItem(1);
myBT->AddItem(10);
myBT->AddItem(4);
myBT->PrintTree();
}
If you want to use the binary tree as a priority queue, you extract the maximum element by stepping only through right child pointers. Any left child would be smaller than the current element. So you record the value of that node and then remove it -- you would still have to write a node deletion routine.
The problem with a simple BST is that it can become unbalanced and send your complexities to O(n). You can use a self-balancing BST, but it's unusual for priority queues. Instead of BSTs they are usually heaps, as Kerrek said.
The simplest heap implementation that I know personally is the binary heap. The binary heap is theoretically a type of binary tree although not stored as such. So, depending on whether you had to implement a BST or just a binary tree, it might fit your requirements.
On this line:
BinaryTree<int> *myBT = new BinaryTree();
You need to also specify the type of template you want to instantiate on the right side of the assignment:
BinaryTree<int> *myBT = new BinaryTree<int>();
Because BinaryTree is not a BinaryTree<int>; one is the name of a template (BinaryTree) and one is the name of a specific type of that template (BinaryTree<int>). You can't create instances of plain templates, you have to give it the type of template you want to use all the time.