Write function in C that for given binary (ordered) tree returns pointer to node that is the closest to the root and divisible by 3.
Here is what I have tried:
Node* find_closest(Node* root) {
if(root == NULL)
return NULL;
if(root->number % 3 == 0)
return root;
if(root->left != NULL)
return find_closest(root->left);
if(root->right != NULL)
return find_closest(root->right);
}
But this doesn't seem to be working. Can someone please help me with this problem?
There are two basic ways to search a binary tree. DFS (depth-first search), and BFS (breadth-first search). DFS searches a tree by going as deep as it can in one direction, only going back up and trying other routes when it finds a dead-end. BFS searches the entire first layer of the tree, then the entire second layer of the tree and so on until it finds what it's looking for.
DFS is very easy to implement with recursion, and appears to be what you were trying to do with your code, but based on the problem you're trying to solve, BFS is a more appropriate algorithm to use, however it is a bit harder to implement because it involves a queue.
Here's an example implementation of BFS that should serve your purposes:
struct nodeQueue{ //This struct lets us store Node pointers in a queue
Node *node;
struct nodeQueue *next;
};
Node* find_closest(Node *root){
if(!root)
return NULL; //Just in case
//Head and tail let us manage the queue of nodes that need to be searched next
struct nodeQueue *head = malloc(sizeof(struct nodeQueue));
struct nodeQueue *tail = head;
*head = (struct nodeQueue){.node = root,.next = NULL}; //root is first in line
while(head){ //As long as there are nodes to check
Node *check = head->node; //Let's pull the next node out of the queue
if(check->number % 3 == 0){ //It is divisible by three so we're done
while(head){ //Free queue to prevent memory leak
struct nodeQueue *hold = head->next;
free(head);
head = hold;
}
return check; //return the node we found
}
//...otherwise
//We need to add the left and right nodes to the queue so they can wait their turn
if(check->left){ //If there is a node to the left put it at the end of the queue
tail->next = malloc(sizeof(struct nodeQueue));
tail = tail->next;
*tail = (struct nodeQueue){.node = check->left,.next = NULL};
}
if(check->right){ //If there is a node to the right put it at the end of the queue
tail->next = malloc(sizeof(struct nodeQueue));
tail = tail->next;
*tail = (struct nodeQueue){.node = check->right,.next = NULL};
}
struct nodeQueue *hold = head->next;
free(head);
head = hold; //Remove the node we just checked so the loop starts with the node next in line
} //If this loop breaks it means none of the nodes' numbers are divisible by three
return NULL;
}
Ensure stdlib.h is included for malloc() and free() and you must be using at least C99 for compound literals to work.
Algorithmically, using a breadth-first search instead of a depth-first search is the most natural solution for finding the node closest to the root (in terms of depth in the tree) that meets a particular criterion. That means testing all the nodes at each depth before testing any deeper nodes, which allows you to test the smallest number of nodes. Read up on breadth-first search if you want to consider this.
Alternatively, you can do it with a depth-first search such as you are presently using, but to do so, you need to track and report back additional data. Specifically, the depth at which the returned result was found, or an equivalent. For example, consider this:
/*
* Finds and returns one of the nodes among those whose number is evenly
* divisible by three and that share a minimum distance from the specified
* root, or returns null if the tree does not contain any nodes with numbers
* divisible by three
*
* root: a pointer to the root node of the tree
* result_depth: a pointer to a `size_t` wherein the depth of the result node
* should be written
*/
Node *find_closest_helper(Node *root, size_t *result_depth);
That can be implemented as a recursive depth-first search, with the result_depth argument used to pass the information between calls that is necessary to favor the nodes closer to the root. The "_helper" part of the function name is meant to convey that you can preserve the function signature presented in the question by making that function a (non-recursive) wrapper around this one.
I have an AVL Tree. Each node looks like this:
typedef struct {
Node *parent; // the parent node
Node *left; // the node left of this node
Node *right; // the node right of this node
int height; // the height of this node
void *value; // payload
} Node;
Is it possible to iterate over an AVL tree with these nodes in O(1) space, without recursion, if yes, how?
If not, a solution with sub-O(n) space or iff really necessary O(N) space is appreciated as well.
With iterating over the tree I mean I want to visit each node once, and if possible in order (from the mostleft to the mostright node).
If you store the last node you have visited, you can derive the next node to visit in an iterator.
If the last node was your parent, go down the left subtree.
If the last node was your left subtree, go down the right subtree.
If the last node was your right subtree, go to your parent.
This algorithm gives you a traversal in O(1) for the tree. You need to flesh it out a little for the leaves and decide what kind of iterator (pre/in/post-order) you want to decide where the iterator should and wait for incrementation.
It is possible to get the next in-order node given a pointer to some node, as long as you keep parent pointers. This can be used to iterate the tree, starting with the leftmost node. From my implementation of AVL tree:
BAVLNode * BAVL_GetNext (const BAVL *o, BAVLNode *n)
{
if (n->link[1]) {
n = n->link[1];
while (n->link[0]) {
n = n->link[0];
}
} else {
while (n->parent && n == n->parent->link[1]) {
n = n->parent;
}
n = n->parent;
}
return n;
}
To get the leftmost node:
BAVLNode * BAVL_GetFirst (const BAVL *o)
{
if (!o->root) {
return NULL;
}
BAVLNode *n = o->root;
while (n->link[0]) {
n = n->link[0];
}
return n;
}
Here, node->link[0] and node->link[1] are the left and right child of the node, respectively, and node->parent is the pointer to the parent node (or NULL for root).
A single GetNext() operation has O(logn) time complexity. However, when used to iterate the entire tree, you get O(n) amortized time complexity.
"Datastructures and their algorithms" by Harry Lewis and Larry Denenberg describe link inversion traversal for constant space traversal of a binary tree. For this you do not need parent pointer at each node. The traversal uses the existing pointers in the tree to store path for back tracking. 2-3 additional node references are needed. Plus a bit on each node to keep track of traversal direction (up or down) as we move down. In my implementation of this algorithms from the book, profiling shows that this traversal has far less memory / processor time. An implementation in java (c would be faster i guess) is here.
I have two questions about binary search trees - one about the code I am writing and the other more about theory. First of all, the code that I wrote below works fine except for when I try to display the case where the BST is actually empty; it gives me a segmentation fault when I would like it to print out an error message. I feel like I may have gotten my pointers mixed up at some point and so that is giving me the error. Here is my code:
#include <stdio.h>
#include <stdlib.h>
struct Node {
char *word;
struct Node *left;
struct Node *right;
};
/* Function that creates a new node as a leaf; that is, its */
/* left and right children are NULL. */
/* Require: node -> word != NULL */
struct Node * createNode (char *word) {
struct Node *item = malloc(sizeof(struct Node));
item -> word = word;
item -> left = NULL;
item -> right = NULL;
return item;
}
/* Recursive function that inserts a node into proper position by */
/* searching through tree. */
struct Node * insertNode (struct Node *root, char *word) {
// If tree is empty, node becomes root
if(root == NULL)
return createNode(word);
else {
if(strcmp(word, root -> word) < 0) {
root -> left = insertNode(root -> left, word);
return root;
} else if(strcmp(word, root -> word) > 0) {
root -> right = insertNode(root -> right, word);
return root;
} else if(strcmp(word, root -> word) == 0)
printf("Word is already present in the tree.");
}
}
/* Function to display Binary Search Tree via inorder traversal. */
/* -- prints entire left subtree, then root, then right subtree */
void display (struct Node *root) {
if(root -> word == NULL)
printf("Tree is empty.");
if(root -> left != NULL)
display(root -> left);
printf("%s\n", root -> word);
if(root -> right != NULL)
display(root -> right);
}
void main () {
struct Node root;
struct Node *rootP = &root;
root = createNode("
}
The second question involves populating the binary tree. I want to use a small dictionary which will of course be in alphabetical order. If I feed those words into the binary tree starting with, say, "aardvark," won't the tree end up incredibly skewed as all subsequent words will come after the first alphabetically and thus always be right children? I'm afraid that I will end up with a tree that is incredibly off balance! Is there some method I can use to shuffle the tree around as I am populating it?
Thank you for taking the time to read this!
In your display function, you first need to test whether root == null before testing whether root -> word == null. That should fix the seg fault.
Regarding the theory question: the answer is that yes, the tree will end up incredibly skewed. That's what balanced binary trees are all about.
if(root -> word == NULL)
printf("Tree is empty.");
Your problem lies here. What happens if root itself is null? Double check that pointer before de-referencing it.
Yes, if you insert items in sorted order (or relatively sorted), you'll get a skewed tree. Look into algorithms on rotations for nodes in balanced binary trees.
Regarding your second question, others have already mentioned looking into balancing your binary tree. However, as an alternative, if your input is already known to be sorted, then it is more appropriate instead to use a linear array with a binary search to find items of interest, rather than a binary tree. A binary search of a sorted array has the same time complexity as a search in a balanced binary tree.
I am trying to figure out an algorithm to delete from the middle of a linked list..
My idea is to traverse the list, find the node right before the node I want to delete, call it Nprev, and set Nprev to Nnext where Nnext is after the node to delete Ndelete.
So Nprev -> Ndelte -> Nnext.
My problem is that I cannot figure out how to traverse this list to find the node before the one I want.
I've been doing this with seg faults because I assign pointers out of range I assume.
Its a very messy algorithm that I have, with many if else statements..
Is there an easier way to do this?
Basically I need to go through the list, apply a function to each node to test if
it is true or false. If false I delete the node.
Deleting first and last is not as hard but middle stumped me.
Please let me know if there are some general ways to solve this problem. I've
been scouring the internet and found nothing I need.
I used this: http://www.cs.bu.edu/teaching/c/linked-list/delete/
but the algorithm before step 4 only deletes the first node in my list
and doesn't do any more.
How can I modify this?
They also give a recursive example but I don't understand it and am intimidated by it.
First you need to find the middle node.
Well take 3 pointers fast, slow, prev
with fast moving with twice the speed of slow and prev storing the address of the node previous of slow.
i.e.
*slow=&head,*fast=&head,prev=Null
traverse the list and when fast=NULL
slow will point to the middle node if number of elements are odd and prev will store the address of node previous of the mid node.
so simply
prev->next=slow->next.
Here an example of something I use to search and remove by index:
Given this struct: (Can also be adapted to other self referencing structs)
struct node
{
S s;
int num;
char string[10];
struct node *ptr;
};
typedef struct node NODE;
Use this to remove an item from somewhere in the "middle" of the list (by index)
int remove_by_index(NODE **head, int n) /// tested, works
{
int i = 0;
int retval = -1;
NODE * current = *head;
NODE * temp_node = NULL;
if (n == 0) {
return pop(head);
}
for (int i = 0; i < n-1; i++) {
if (current->ptr == NULL) {
return -1;
}
current = current->ptr;
}
temp_node = current->ptr;
retval = temp_node->num;
current->ptr = temp_node->ptr;
free(temp_node);
return retval;
}
Is it possible to delete a middle node in the single linked list when the only information available we have is the pointer to the node to be deleted and not the pointer to the previous node?After deletion the previous node should point to the node next to deleted node.
It's definitely more a quiz rather than a real problem. However, if we are allowed to make some assumption, it can be solved in O(1) time. To do it, the strictures the list points to must be copyable. The algorithm is as the following:
We have a list looking like: ... -> Node(i-1) -> Node(i) -> Node(i+1) -> ... and we need to delete Node(i).
Copy data (not pointer, the data itself) from Node(i+1) to Node(i), the list will look like: ... -> Node(i-1) -> Node(i+1) -> Node(i+1) -> ...
Copy the NEXT of second Node(i+1) into a temporary variable.
Now Delete the second Node(i+1), it doesn't require pointer to the previous node.
Pseudocode:
void delete_node(Node* pNode)
{
pNode->Data = pNode->Next->Data; // Assume that SData::operator=(SData&) exists.
Node* pTemp = pNode->Next->Next;
delete(pNode->Next);
pNode->Next = pTemp;
}
Mike.
Let's assume a list with the structure
A -> B -> C -> D
If you only had a pointer to B and wanted to delete it, you could do something like
tempList = B->next;
*B = *tempList;
free(tempList);
The list would then look like
A -> B -> D
but B would hold the old contents of C, effectively deleting what was in B. This won't work if some other piece of code is holding a pointer to C. It also won't work if you were trying to delete node D. If you want to do this kind of operation, you'll need to build the list with a dummy tail node that's not really used so you guarantee that no useful node will have a NULL next pointer. This also works better for lists where the amount of data stored in a node is small. A structure like
struct List { struct List *next; MyData *data; };
would be OK, but one where it's
struct HeavyList { struct HeavyList *next; char data[8192]; };
would be a bit burdensome.
Not possible.
There are hacks to mimic the deletion.
But none of then will actually delete the node the pointer is pointing to.
The popular solution of deleting the following node and copying its contents to the actual node to be deleted has side-effects if you have external pointers pointing to nodes in the list, in which case an external pointer pointing to the following node will become dangling.
I appreciate the ingenuity of this solution (deleting the next node), but it does not answer the problem's question. If this is the actual solution, the correct question should be "delete from the linked list the VALUE contained in a node on which the pointer is given". But of course, the correct question gives you a hint on solution.
The problem as it is formulated, is intended to confuse the person (which in fact has happened to me, especially because the interviewer did not even mention that the node is in the middle).
One approach would be to insert a null for the data. Whenever you traverse the list, you keep track of the previous node. If you find null data, you fix up the list, and go to the next node.
The best approach is still to copy the data of the next node into the node to be deleted, set the next pointer of the node to the next node's next pointer, and delete the next node.
The issues of external pointers pointing to the node to be deleted, while true, would also hold for the next node. Consider the following linked lists:
A->B->C->D->E->F and G->H->I->D->E->F
In case you have to delete node C (in the first linked list), by the approach mentioned, you will delete node D after copying the contents to node C. This will result in the following lists:
A->B->D->E->F and G->H->I->dangling pointer.
In case you delete the NODE C completely, the resulting lists will be:
A->B->D->E->F and G->H->I->D->E->F.
However, if you are to delete the node D, and you use the earlier approach, the issue of external pointers is still there.
The initial suggestion was to transform:
a -> b -> c
to:
a ->, c
If you keep the information around, say, a map from address of node to address of the next node then you can fix the chain the next time to traverse the list. If need to delete multiple items before the next traversal then you need to keep track of the order of deletes (i.e. a change list).
The standard solution is consider other data structures like a skip list.
Maybe do a soft delete? (i.e., set a "deleted" flag on the node) You can clean up the list later if you need to.
Not if you want to maintain the traversability of the list. You need to update the previous node to link to the next one.
How'd you end up in this situation, anyway? What are you trying to do that makes you ask this question?
You'll have to march down the list to find the previous node. That will make deleting in general O(n**2). If you are the only code doing deletes, you may do better in practice by caching the previous node, and starting your search there, but whether this helps depends on the pattern of deletes.
Given
A -> B -> C -> D
and a pointer to, say, item B, you would delete it by
1. free any memory belonging to members of B
2. copy the contents of C into B (this includes its "next" pointer)
3. delete the entire item C
Of course, you'll have to be careful about edge cases, such as working on lists of one item.
Now where there was B, you have C and the storage that used to be C is freed.
Considering below linked list
1 -> 2 -> 3 -> NULL
Pointer to node 2 is given say "ptr".
We can have pseudo-code which looks something like this:
struct node* temp = ptr->next;
ptr->data = temp->data;
ptr->next = temp->next;
free(temp);
yes, but you can't delink it. If you don't care about corrupting memory, go ahead ;-)
Yes, but your list will be broken after you remove it.
In this specific case, traverse the list again and get that pointer! In general, if you are asking this question, there probably exists a bug in what you are doing.
In order to get to the previous list item, you would need to traverse the list from the beginning until you find an entry with a next pointer that points to your current item. Then you'd have a pointer to each of the items that you'd have to modify to remove the current item from the list - simply set previous->next to current->next then delete current.
edit: Kimbo beat me to it by less than a minute!
You could do delayed delinking where you set nodes to be delinked out of the list with a flag and then delete them on the next proper traversal. Nodes set to be delinked would need to be properly handled by the code that crawls the list.
I suppose you could also just traverse the list again from the beginning until you find the thing that points to your item in the list. Hardly optimal, but at least a much better idea than delayed delinking.
In general, you should know the pointer to the item you just came from and you should be passing that around.
(Edit: Ick, with the time it took me to type out a fullish answer three gazillion people covered almost all the points I was going to mention. :()
The only sensible way to do this is to traverse the list with a couple of pointers until the leading one finds the node to be deleted, then update the next field using the trailing pointer.
If you want to delete random items from a list efficiently, it needs to be doubly linked. If you want take items from the head of the list and add them at the tail, however, you don't need to doubly link the whole list. Singly link the list but make the next field of the last item on the list point to the first item on the list. Then make the list "head" point to the tail item (not the head). It is then easy to add to the tail of the list or remove from the head.
You have the head of the list, right? You just traverse it.
Let's say that your list is pointed to by "head" and the node to delete it "del".
C style pseudo-code (dots would be -> in C):
prev = head
next = prev.link
while(next != null)
{
if(next == del)
{
prev.link = next.link;
free(del);
del = null;
return 0;
}
prev = next;
next = next.link;
}
return 1;
The following code will create a LL, n then ask the user to give the pointer to the node to be deleted. it will the print the list after deletion
It does the same thing as is done by copying the node after the node to be deleted, over the node to be deleted and then delete the next node of the node to be deleted.
i.e
a-b-c-d
copy c to b and free c so that result is
a-c-d
struct node
{
int data;
struct node *link;
};
void populate(struct node **,int);
void delete(struct node **);
void printlist(struct node **);
void populate(struct node **n,int num)
{
struct node *temp,*t;
if(*n==NULL)
{
t=*n;
t=malloc(sizeof(struct node));
t->data=num;
t->link=NULL;
*n=t;
}
else
{
t=*n;
temp=malloc(sizeof(struct node));
while(t->link!=NULL)
t=t->link;
temp->data=num;
temp->link=NULL;
t->link=temp;
}
}
void printlist(struct node **n)
{
struct node *t;
t=*n;
if(t==NULL)
printf("\nEmpty list");
while(t!=NULL)
{
printf("\n%d",t->data);
printf("\t%u address=",t);
t=t->link;
}
}
void delete(struct node **n)
{
struct node *temp,*t;
temp=*n;
temp->data=temp->link->data;
t=temp->link;
temp->link=temp->link->link;
free(t);
}
int main()
{
struct node *ty,*todelete;
ty=NULL;
populate(&ty,1);
populate(&ty,2);
populate(&ty,13);
populate(&ty,14);
populate(&ty,12);
populate(&ty,19);
printf("\nlist b4 delete\n");
printlist(&ty);
printf("\nEnter node pointer to delete the node====");
scanf("%u",&todelete);
delete(&todelete);
printf("\nlist after delete\n");
printlist(&ty);
return 0;
}
void delself(list *list)
{
/*if we got a pointer to itself how to remove it...*/
int n;
printf("Enter the num:");
scanf("%d",&n);
while(list->next!=NULL)
{
if(list->number==n) /*now pointer in node itself*/
{
list->number=list->next->number; /*copy all(name,rollnum,mark..)
data of next to current, disconnect its next*/
list->next=list->next->next;
}
list=list->next;
}
}
If you have a linked list A -> B -> C -> D and a pointer to node B. If you have to delete this node you can copy the contents of node C into B, node D into C and delete D. But we cannot delete the node as such in case of a singly linked list since if we do so, node A will also be lost. Though we can backtrack to A in case of doubly linked list.
Am I right?
void delself(list *list)
{
/*if we got a pointer to itself how to remove it...*/
int n;
printf("Enter the num:");
scanf("%d",&n);
while(list->next!=NULL)
{
if(list->number==n) /*now pointer in node itself*/
{
list->number=list->next->number;
/*copy all(name,rollnum,mark..) data of next to current, disconect its next*/
list->next=list->next->next;
}
list=list->next;
}
}
This is a piece of code I put together that does what the OP was asking for, and can even delete the last element in the list (not in the most elegant way, but it gets it done). Wrote it while learning how to use linked lists. Hope it helps.
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>
using namespace std;
struct node
{
int nodeID;
node *next;
};
void printList(node* p_nodeList, int removeID);
void removeNode(node* p_nodeList, int nodeID);
void removeLastNode(node* p_nodeList, int nodeID ,node* p_lastNode);
node* addNewNode(node* p_nodeList, int id)
{
node* p_node = new node;
p_node->nodeID = id;
p_node->next = p_nodeList;
return p_node;
}
int main()
{
node* p_nodeList = NULL;
int nodeID = 1;
int removeID;
int listLength;
cout << "Pick a list length: ";
cin >> listLength;
for (int i = 0; i < listLength; i++)
{
p_nodeList = addNewNode(p_nodeList, nodeID);
nodeID++;
}
cout << "Pick a node from 1 to " << listLength << " to remove: ";
cin >> removeID;
while (removeID <= 0 || removeID > listLength)
{
if (removeID == 0)
{
return 0;
}
cout << "Please pick a number from 1 to " << listLength << ": ";
cin >> removeID;
}
removeNode(p_nodeList, removeID);
printList(p_nodeList, removeID);
}
void printList(node* p_nodeList, int removeID)
{
node* p_currentNode = p_nodeList;
if (p_currentNode != NULL)
{
p_currentNode = p_currentNode->next;
printList(p_currentNode, removeID);
if (removeID != 1)
{
if (p_nodeList->nodeID != 1)
{
cout << ", ";
}
cout << p_nodeList->nodeID;
}
else
{
if (p_nodeList->nodeID !=2)
{
cout << ", ";
}
cout << p_nodeList->nodeID;
}
}
}
void removeNode(node* p_nodeList, int nodeID)
{
node* p_currentNode = p_nodeList;
if (p_currentNode->nodeID == nodeID)
{
if(p_currentNode->next != NULL)
{
p_currentNode->nodeID = p_currentNode->next->nodeID;
node* p_temp = p_currentNode->next->next;
delete(p_currentNode->next);
p_currentNode->next = p_temp;
}
else
{
delete(p_currentNode);
}
}
else if(p_currentNode->next->next == NULL)
{
removeLastNode(p_currentNode->next, nodeID, p_currentNode);
}
else
{
removeNode(p_currentNode->next, nodeID);
}
}
void removeLastNode(node* p_nodeList, int nodeID ,node* p_lastNode)
{
node* p_currentNode = p_nodeList;
p_lastNode->next = NULL;
delete (p_currentNode);
}
Void deleteMidddle(Node* head)
{
Node* slow_ptr = head;
Node* fast_ptr = head;
Node* tmp = head;
while(slow_ptr->next != NULL && fast_ptr->next != NULL)
{
tmp = slow_ptr;
slow_ptr = slow_ptr->next;
fast_ptr = fast_ptr->next->next;
}
tmp->next = slow_ptr->next;
free(slow_ptr);
enter code here
}