I'm trying to make complete tree from scratch in C++:
1st node = root
2nd node = root->left
3rd node = root->right
4th node = root->left->left
5th node = root->left->right
6th node = root->right->left
7th node = root->right->right
where the tree would look something like this:
NODE
/ \
NODE NODE
/ \ / \
NODE NODE NODE NODE
/
NEXT NODE HERE
How would I go about detecting where the next node would go so that I can just use one function to add new nodes? For instance, the 8th node would be placed at root->left->left->left
The goal is to fit 100 nodes into the tree with a simple for loop with insert(Node *newnode) in it rather than doing one at a time. It would turn into something ugly like:
100th node = root->right->left->left->right->left->left
Use a queue data structure to accomplish building a complete binary tree. STL provides std::queue.
Example code, where the function would be used in a loop as you request. I assume that the queue is already created (i.e. memory is allocated for it):
// Pass double pointer for root, to preserve changes
void insert(struct node **root, int data, std::queue<node*>& q)
{
// New 'data' node
struct node *tmp = createNode(data);
// Empty tree, initialize it with 'tmp'
if (!*root)
*root = tmp;
else
{
// Get the front node of the queue.
struct node* front = q.front();
// If the left child of this front node doesn’t exist, set the
// left child as the new node.
if (!front->left)
front->left = tmp;
// If the right child of this front node doesn’t exist, set the
// right child as the new node.
else if (!front->right)
front->right = tmp;
// If the front node has both the left child and right child, pop it.
if (front && front->left && front->right)
q.pop();
}
// Enqueue() the new node for later insertions
q.push(tmp);
}
Suppose root is node#1, root's children are node#2 and node#3, and so on. Then the path to node#k can be found with the following algorithm:
Represent k as a binary value, k = { k_{n-1}, ..., k_0 }, where each k_i is 1 bit, i = {n-1} ... 0.
It takes n-1 steps to move from root to node#k, directed by the values of k_{n-2}, ..., k_0, where
if k_i = 0 then go left
if k_i = 1 then go right
For example, to insert node#11 (binary 1011) in a complete tree, you would insert it as root->left->right->right (as directed by 011 of the binary 1011).
Using the algorithm above, it should be straightforward to write a function that, given any k, insert node#k in a complete tree to the right location. The nodes don't even need to be inserted in-order as long as new nodes are detected created properly (i.e. as the correct left or right children, respectively).
Assuming tree is always complete we may use next recursion. It does not gives best perfomance, but it is easy to understand
Node* root;
Node*& getPtr(int index){
if(index==0){
return root;
}
if(index%2==1){
return (getPtr( (index-1)/2))->left;
}
else{
return (getPtr( (index-2)/2))->right;
}
}
and then you use it like
for(int i = 0; i<100; ++i){
getPtr(i) = new Node( generatevalue(i) );
}
private Node addRecursive(*Node current, int value) {
if (current == null) {
return new Node(value);
}
if (value < current.value) {
current->left = addRecursive(current->left, value);
} else if (value > current->value) {
current->right = addRecursive(current->right, value);
} else {
// value already exists
return current;
}
return current;
}
I do not know that if your Nodes has got a value instance but:
With this code you can have a sorted binary tree by starting from the root.
if the new node’s value is lower than the current node’s, we go to the left child. If the new node’s value is greater than the current node’s, we go to the right child. When the current node is null, we’ve reached a leaf node and we can insert the new node in that position.
Related
Value of node in *node=*(node->next), if node is the last element in linked list?
Value of node would be NULL or not?
Given a singly linked list consisting of N nodes. The task is to remove duplicates (nodes with duplicate values) from the given list (if exists).
Note: Try not to use extra space. Expected time complexity is O(N). The nodes are arranged in a sorted way.
This solution didn't work for test case 2 2 2 2 2 (five nodes with equal values).
Node *removeDuplicates(Node *root)
{
if(root->next==NULL)
return root;
Node * t1=root;
Node* t2=root->next;
while(t2!=NULL)
{
if(t1->data==t2->data)
{
*t2=*(t2->next);
}
else
{
t1=t1->next;
t2=t2->next;
}
}
return root;
}
This worked:
Node *removeDuplicates(Node *root)
{
if(root->next==NULL)
return root;
Node * t1=root;
Node* t2=root->next;
while(t2!=NULL)
{
if(t1->data==t2->data)
{
if(t2->next==NULL)
{
t1->next=NULL;
t2=NULL;
}
else
{
*t2=*(t2->next);
}
}
else
{
t1=t1->next;
t2=t2->next;
}
}
return root;
}
Normally I wouldn't post the full code for something that is clearly homework but I wasn't sure how to properly articulate all of the points. I also haven't compiled and ran this because I didn't want to create my own Node class.
First we can talk about the algorithm. If your singly linked list is already sorted and NULL terminated then essentially we have a current node pointing to a node in the list and a travel node (nextNode) that walks down the list. The main thing we need to make sure we do is update the pointers to point to the next node once we've found a non-duplicate.
In the code below I've also added NULL checks which is incredibly important. Get in the habit of knowing exactly which state your variables could be in as it is easy to accidentally call a method on a null pointer which would cause the program to crash.
Node* removeDuplicates(Node* root)
{
// Check that root isn't null before checking that its next pointer is also not NULL
if (root == NULL || root->next == NULL)
return root;
// Set up our current node and the travel node
Node* currentNode = root;
Node* nextNode = root->next;
// Until we've reached the end of the singly linked list
while (nextNode != NULL)
{
// Find the next node that isn't a duplicate
// Also check that we don't reach the end of the list
while (nextNode->data == currentNode->data && nextNode != NULL)
nextNode = nextNode.next;
// Update the current node's next pointer to point to the travel node
currentNode->next = nextNode;
// Update the current node to its next for the next iteration
currentNode = nextNode;
// Update the next node being careful to check for NULL
nextNode = nextNode == NULL ? NULL : nextNode->next;
}
return root;
}
This is not the only way to handle this problem. By reorganizing when you do certain checks and associations you can eliminate some of the NULL checks or make the program more clear. This is just one possible solution.
So I have a pretty good understanding of iterating through a linked list, and also obtaining the next node in the list. Now I trying to go in the other direction, but I soon realized its not as easy as it appears. Unlike an array where you can iterate forwards and backwards. I seem to be stumped.
So If I have a list of 1 -> 2 -> 3 -> 4 -> NULL How would I go about obtaining the address of node 2 given the location of node 3?
I started messing around with this code below which returns all items up to node 3. I just don't see how I can get that previous node? By the way searchList() returns the address of a node if you give it the node->data value. Using the list above searchList(3) returns the address of the node which has 3 as its data member.
struct node {
int data;
node* next;
};
void llclass::getPrevious() {
node *stop = searchList(nodeItem),
*start = head;
while (start != stop) {
cout << start->data << endl;
start = start->next;
}
}
With a singly-linked list like yours, it is not possible to obtain the address of node 2 if you're given only the address of node 3. You would have to start at the head node and iterate forward until reaching 3, keeping track of the previous node (2 in this case). Alternately, you could use a doubly-linked list that includes a "node *previous;" member.
Sounds like you want to get the previous node of a node whose value is given as input to you. This should do that for you:
node* llclass::getPrevious(int item)
{
node* previous = NULL;
node* current = head;
while(current)
{
if (current->data == item)
{
return previous;
}
else
{
previous = current;
current = current->next;
}
}
return NULL;
}
I want to make a queue using linked lists.
There are numerous algorithms out there for that. But what i'm curious in is how to make a relative priority queue.
Maybe there is a special name for this type of queue, but i don't know it, and i haven't had any luck googling for the solution.
Anyways, let's say i have this struct, which will represent the Node of my list.
struct Node {
int value;
Node* next;
}
if i want to create a priority queue (where the element with the least value is first), when i insert for example 5 7 1 8 2, my list should look like this:
1 -> 2 -> 5 -> 7 -> 8
It's not really hard to implement that.
What i want to do is - when i insert the first element, other elements should have value relative to the previous element. So, in my example, the list/queue would contain the following values:
1 -> 1 -> 3 -> 2 -> 1
I'm not really sure how i would implement that? Would the following idea be applicable:
in the Node struct i add another field, which would represent the original value.
i find the position of the node i'm inserting the same way i would do when creating an ordinary linked list, and then i just say
temp->value = temp->originalValue - previous->originalValue;
You need to store extra data in each node, either the relative priority, or a "previous" pointer. Since the next node's relative priority needs to updated whenever a node is removed (how to do that without a prev pointer?), I suggest the "previous" pointer:
struct Node {
int value;
Node* next;
Node* prev;
}
Then a function can evaluate the relative priority:
int relative_priority(Node* node) {
if (node == NULL)
return 0;
if (node->prev == NULL)
return node->value;
return node->value - node->prev->value;
}
Note that I'm using C, you'll need to replace NULL with 0 for C++
You first have to identify where to insert the new node. This involves decrements on the target value, adjusting its relative value in relation to the current in the list. At the point of insertion, you have to point the previous node to the new node, and then adjust the node ahead of the new node with a new relative value.
Node * create_node (int value, Node *next) { /* ... */ }
void insert_relative_priority_queue (Node **head, int value) {
Node **prev = head, *cur;
if (*head) {
cur = *head;
while (value > cur->value) {
value -= cur->value;
prev = &cur->next;
cur = cur->next;
if (cur == 0) break;
}
*prev = create_node(value, cur);
if (cur) {
cur->value -= value;
}
} else {
*head = create_node(value, 0);
}
}
When you remove from the front of the list, you adjust the value of the new head:
void remove_relative_priority_queue (Node **head) {
if (*head) {
Node *cur = *head;
*head = cur->next;
if (*head) {
(*head)->value += cur->value;
}
free(cur);
}
}
This my my successor func:
int
BalancedTree::successor( TreeNode *node ) // successor is the left-most child of its right subtree,
{
TreeNode *tmp = node;
int successorVal = -1;
tmp = tmp->m_RChild;
if( NULL != tmp )
{
while( NULL != tmp->m_LChild )
tmp = tmp->m_LChild;
// now at left most child of right subtree
successorVal = tmp->m_nodeData;
}
return successorVal;
} // successor()
my instructor gave us a file filled with random data. I place all this data into the tree, the insert method works, but once the remove method starts, the successor function at some point returns the same value of the the node I'm looking for a successor for. This shouldn't be able to happen correct? is my successor function correct? If you want to see the remove method just mention it.
Your definition of successor is flawed already: if the node doesn't have a right node the successor is one of its ancestors: the first one whose left child is the node or one of its ancestors. Only if no such ancestor exists there is mo successor. Personally I would return an iterator to the node but otherwise the code seems to be OK.
I am building a binary tree. The binary tree is pre-built in a file and I need to construct it. Due to the way it is structured, I read the tree into an array. Each tree nodes look something like this.
struct Tree_Node
{
float normalX;
float normalY;
float normalZ;
float splitdistance;
long region;
long left, right; //array index
Tree_Node* left_node; // pointer to left node
Tree_Node* right_node; // pointer to right node
} typedef Tree_Node;
I have tried a number of ways to write some code that will build the tree. Let me give you some pseudocode so you understand what I am trying to do.
Read in head node. Node is number one in the array.
If the node has a right and left array index, create new nodes and
insert the information from the array
indicies into that tree node.
If the node does not have a right and left index, it is a leaf node.
Here is my building function:
void WLD::treeInsert(BSP_Node *tree_root, int node_number)
{
/// Add the item to the binary sort tree to which the parameter
// "root" refers. Note that root is passed by reference since
// its value can change in the case where the tree is empty.
if ( tree_root == NULL )
{
// The tree is empty. Set root to point to a new node containing
// the new item. This becomes the only node in the tree.
tree_root = new BSP_Node();
tree_root->normalX = bsp_array[node_number].normal[0];
tree_root->normalY = bsp_array[node_number].normal[1];
tree_root->normalZ = bsp_array[node_number].normal[2];
tree_root->splitdistance = bsp_array[node_number].splitdistance;;
tree_root->region = bsp_array[node_number].region;
tree_root->left = bsp_array[node_number].left;
tree_root->right = bsp_array[node_number].right;
tree_root->left_node[node_number];
tree_root->right_node[node_number];
errorLog.OutputSuccess("Inserting new root node: %i", node_number);
// NOTE: The left and right subtrees of root
// are automatically set to NULL by the constructor.
// This is important...
}
if ( tree_root->left != 0 )
{
errorLog.OutputSuccess("Inserting left node number: %i!", tree_root->left);
treeInsert( tree_root->left_node, tree_root->left );
}
else if ( tree_root->right != 0 )
{
errorLog.OutputSuccess("Inserting right node: %i!", tree_root->right);
treeInsert( tree_root->right_node, tree_root->right );
}
else if ( tree_root->right == 0 && tree_root->left == 0)
{
errorLog.OutputSuccess("Reached a leaf node!");
return;
}
else
{
errorLog.OutputError("Unknown BSP tree error!");
}
}
My debug shows that the function tries to insert node 2 until the program crashes.
Can someone help me with this?
tree_root->left_node[node_number];
I don't see any code that initializes this array, so this'll be referring to something invalid.
Then by the time you come around to the next function
treeInsert( tree_root->left_node, tree_root->left );
treeInsert will be called with an invalid pointer, since left_node doesn't go anywhere.
I imagine you need something like tree_root->left_node = NULL instead of tree_root->left_node[node_number] so that the recursive call to treeInsert creates the next node.