Two questions on Binary Search Trees - c

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.

Related

Function in C that for given binary (ordered) tree returns pointer to node that is the closest to the root and divisible by 3

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.

How to create a linked list that points to the nodes of a binary tree?

I have a function that creates a binary tree, and for each node in the tree, I need to add a node to a separate linked list that points to the node in the binary tree.
My function to create the binary tree:
typedef struct myTree _node;
void INSERT(_node *(*tree), _node *item) {
if (!(*tree)) {
*tree = item;
return;
}
if (item->val < (*tree)->val) {
INSERT(&(*tree)->left, item);
}
else if (item->val > (*tree)->val) {
INSERT(&(*tree)->right);
}
}
My main function:
int main(void) {
int i;
int *balanced;
_node *current, *root;
root = NULL;
for (i = 0; i < size; i++) {
current = (_node *)malloc(sizeof(_node));
current->left = current->right = NULL;
current->val = balanced[i];
INSERT(&root, current);
}
return 0;
}
I've left out parts of my main function for simplicity.
The idea is that I want to print out the contents of the tree in pre, in, and post order, as well as traverse the linked list and print the value of the node in the tree that each linked list node points to.
I'm only a few months into learning C, so I am not terribly advanced.
Much like your insert function is recursive on the tree, walking the tree is recursive as well. There are two ways to do this: the specific way and the generic way. Let's see both.
The specific way just prints values as it encounters them. It solves this specific problem: printing the values. If you have to do tree walks to do more than one thing, you'd have to copy the code, which is generally a bad thing.
On the other hand, the code is much simpler and easier to follow. Let's look at the in-order case (you can do the other two by yourself; they are very similar):
void print_in_order (const struct myTree * tree) {
// if we're in a null node, do nothing
if (!tree) return;
// otherwise, do the left subtree, then the current node, then the right subtree
// non-existent subtrees will be handled by the above check, so don't check twice
print_in_order(tree -> left);
printf("%d\n", tree -> val);
print_in_order(tree -> right);
}
The generic way, on the other hand, is a better approach if your program is doing tree walks for all sorts of purposes. The idea is that you encapsulate the actual task to be done at each node (in this case, printing it) in a separate function:
void print_node (const struct myTree * node) {
printf("%d\n", node -> val);
}
And then you write a function that takes this function as an argument and calls it on each node, in the corresponding order. Let's do it for in-order:
void apply_in_order (const struct myTree * tree,
void (* callback)(const struct myTree *)) {
// this is the same as before...
if (!tree) return;
apply_in_order(tree -> left, callback);
// ...except that, instead of doing a specific thing, we call the callback on each node
callback(tree);
apply_in_order(tree -> right, callback);
}
Now, you just call this function as apply_in_order(tree, print_node); and you get the same behavior as above. But the next time you need to write a function that walks a tree, you only need the per-node thing; the rest is already done.

How to convert Doubly linked list to Binary tree

struct cnode
{
int info;
struct cnode *next;
struct cnode *previous;
};
typedef struct cnode cnode;
pre-made DOUBLY LINKED LIST: 1<->2<->3<->4<->5<->6<->7
So I'm trying to make a recursive function that grabs the mid of the doubly linked list (root = 4) and convert it into a the remaining into a binary tree. I'm still new to recursion so an explanation along with code would be GREATLY appreciated!
EX. 4
/ \
2 6
/ \ / \
1 3 5 7
This is the code I have thus far (which isn't much due to difficulties with recursion)
void *convert(cnode *head){
if(head == NULL)
return;
int count = 0;
cnode *tempHead = head;
while(tempHead != NULL){
count++;
tempHead = tempHead->next;
}
int move = (count/2) + (count%2);
int i;
for(i=1; i<move; i++){
head = head->next;
}
}
Pretty much just sets the head pointer to the mid info (4)
I think I understand; you're making a balanced binary tree from cnodes with the previous and next pointers being reused for the left and right sub-trees.
... so that's your algorithm.
Find the middle node of the binary tree (which you've already done).
Turn the left half into a binary tree. The left half is the original head, with the last element (middle->previous) now having a next pointer of NULL.
Link this left half to middle->previous (hijacked as the left sub-tree).
Turn the right half into a binary tree; this is headed by middle->next. Make it the new value of middle->next.
You have to keep the original head as the pointer to the left sub-tree.
You'll want your routine to return the binary tree's root, so the previous call can link it into the level above.
You still have to pick a termination condition, such as the head pointer being NULL.
Does that get you moving to a solution?
I hope this code will help you. call the DLL2BT method with head of the doubly linked list which return the root node of the tree created.
class box
{
int data;
box left=null,right=null;
box(int a)
{
data=a;
}
}
public static box DLL2BT(box head)// head = linked list head
{
if(head!=null)
{
box node=null;
try
{
node = findMid(head);
node.left.right=null;
node.left=DLL2BT(head);
node.right.left=null;
node.right=DLL2BT(node.right);
}
catch( Exception e){ }
return node;
}
return null;
}
public static box findMid(box head)
{
box slow=head,fast=head.right;
try
{
while(fast!=null)
{
slow=slow.right;
fast=fast.right.right;
}
}
catch(Exception e){ }
return slow;
}
Firstly, You are trying to convert DLL to binary tree assuming the DLL is given as in-order of the binary tree you have to make. Note that there isn't a unique tree you can make from only inorder traversal.Even if you have to make BST, you can't make it with only inorder traversal. What I actually think you are trying to do is to convert it into a balanced BST. Even though, it will also not be unique.
Here's the algorithm..
1) Get the Middle of the linked list and make it root.
2) Recursively do same for left half and right half.
  a) Get the middle of left half and make it left child of the root
created in step 1.
  b) Get the middle of right half and make it right child of the
root created in step 1.
Time complexity: O(nLogn) where n is the number of nodes in Linked List.
Although,it can be solved in O(n) if you insert nodes in BST in the same order as the appear in Doubly Linked List.

printing BST - C Program

I am new to C and I am learning functions and pointers. I have to print Binary search tree in the requisite format below in the t_print method and I would be really grateful some could guide me how to go about it.
I have this code till now:
typedef struct tree {
void* data;
struct tree* left;
struct tree* right;
} Tree;
/*set the data on the tree node */
void t_set_data(Tree* t, void* data) {
t->data = data;}
/*let l be the left node of tree *t */
void t_set_left(Tree* t, Tree* l){
t->left = l;}
/*let r be the left node of tree *t */
void t_set_right(Tree* t, Tree* r){
t->right = r;}
/* simply return left node of the tree */
Tree* t_left(Tree* t){
return t-> left;}
/* simply return right node of the tree */
Tree* t_right(Tree* t){
return t-> right;}
/* simply return the data of the tree */
void* t_data(Tree* t){
return t->data;}
/* make the node of the tree and allocate space for it*/
Tree* t_make(){
Tree *t = (Tree*)malloc(sizeof(tree));
t->left=NULL;
t->right = NULL;
t-> data = NULL;
return t;
}
/*
print the whole tree in the following format
Root is printed with zero trailing spaces to the left
Every node/subtree is printed with one additional space
Below is an example for a tree with depth 2:
Root
<space>Left-Child
<space><space>Left-Left-Child
<space><space>Left-Right-Child
<space>Right-Child
.... and so on ...
Use (void(* p))(function pointer) to print.
*/
void t_print( Tree* t ,int space, void(* p)(void*) ){
}
It depends on the order in which you want the data printed, but for a BST, 'in order' is appropriate (as opposed to pre-order or post-order).
To print a tree 'in order', the function does:
If the current node is not null
print the left sub-tree in order
print the current node
print the right sub-tree in order
The 'print the xxx sub-tree in order' operations are recursive calls to the 'print in order' function with the left or right pointer.
The algorithm for pre-order is:
If the current node is not null
print the current node
print the left sub-tree in pre-order
print the right sub-tree in pre-order
The algorithm for post-order is:
If the current node is not null
print the left sub-tree in post-order
print the right sub-tree in post-order
print the current node
And it really is that simple.
Well, nearly that simple...
If you want to bracket the data or otherwise make it possible to identify the tree structure, you have to work a little harder. You also typically end up with a cover function that adds a prefix (tag identifying the output) and a suffix (maybe just a newline); this is not part of the recursive printing, usually. But the core of the algorithm is as simple as described.

Cons Cell data structure in C

I'm a newbie at C, in the early stages of building a small Scheme interpreter. For this part of the project I'm trying to build a simple cons cell data structure. It should take a list like
(a b c)
and represent it internally like so:
[ ][ ] -> [ ][ ] -> [ ][/]
| | |
A B C
To test that it's working correctly, I have a print function to to echo out the input. Here is the code that isn't working:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "lexer.h"
#include "parse.h"
char token[20];
struct conscell {
char *data;
struct conscell *first, *rest;
};
void S_Expression ()
{
/* function from lexer to receive input a split into tokens no greater than 20 */
startTokens(20);
/* gets the next token */
strcpy(token, getToken());
/* List is a typedef for the struct conscell */
List tree = createList ();
tree = nextNode (tree);
printList(tree);
}
List createList ()
{
List node = malloc(sizeof (List));
if (node == NULL) {
printf("Out of memory!\n");
exit(1);
}
node->data = NULL;
node->first = NULL;
node->rest = NULL;
return node;
}
/* Recursive function to build cons cell structure */
List nextNode (List node)
{
node = createList ();
if (token[0] == '(')
{
strcpy(token, getToken());
node->first = nextNode(node->first);
node->rest = nextNode(node->rest);
}
else
{
if (token[0] == ')')
{
node = NULL;
}
else
{
List temp = createList();
temp->data = token;
temp->first = NULL;
temp->rest = NULL;
node->first = temp;
strcpy(token, getToken());
node->rest = nextNode(node->rest);
}
}
return node;
}
/* Prints output. So far, just trying to print symbols */
void printList(List node)
{
if (node != NULL)
{
if (node->data != NULL)
{
printf("%s", node->data);
}
}
}
So far can't print out anything. I'm almost positive its a pointer issue. If anyone could point me (no pun intended) in the right direction, it'd be very much appreciated.
Thank you
First, I'm assuming List is a typedef for a struct conscell*. If it's not, it should be, otherwise your code won't compile without tons of warnings.
A scheme cons cell should be a simple singly linked list, not a doubly-linked list. So your individual cells should be more like:
typedef conscell
{
unsigned char *data; //<== use unsigned char for a memory buffer
struct conscell* next; //<== only a "next" pointer needed
} conscell;
I see you're just trying to print symbols at the moment, so using char rather than unsigned char can work for that purpose, but when you go with more generic data-structures like lambdas, etc., you're going to have to switch to either unsigned char* or void* for the reference to the memory buffer holding those types of more complex data-structures.
The other issue that seems a bit confusing is that you're making each cell of your cons cells another cons cell, for instance, these lines of code,
if (token[0] == '(')
{
strcpy(token, getToken());
node->first = nextNode(node->first);
node->rest = nextNode(node->rest);
}
are recursively adding cons cells as your "first" and "rest" ... but that's not how a linked-list should look like. It should have a pointer to a list-node as the "head" of the list (not another cons-cell like it seems you're doing here), and then each node in the list points to some data and the next node in the list.
Next, you have memory leaks all over the place with your createList() function as you allocate memory with it, but then never delete that memory (i.e., you have code like node = NULL which effectively is a memory leak because you've lost the memory reference to the allocated memory location that node was originally pointing to). You have to call free() on a node pointer before you assign NULL to it.
Finally, printList() doesn't do anything but print the first element of the list you pass it ... there are no recursive calls or loops to cycle to the next node in the linked list. So you're not going to be printing much with that function. It should look more like:
void printList(List node)
{
List current = node;
while (current != NULL) //<== guard for the end-of-list
{
if (node->data != NULL)
{
printf("%s", node->data);
}
current = current->next; //cycle to the next node in the linked list
}
}
So to sum things up, 1) your cons data-structure should represent a singly linked list composed of a structure data-type having a data element and a pointer to the next node. The cons'ed list is accessed through a head pointer pointing to the first node. 2) As you parse the input, you should add nodes to the front of the linked list since Scheme's cons operation, and really all the operations in scheme, are recursive, and "fold to the right", meaning they work from a base-case (i.e., the cons'ing of two elements), and then expand on that base-case. So if you had something like (cons 'd (cons 'c (cons 'b (cons 'a '())))), you'd the print the list (d c b a). If you want, it could also help to put tokens into a stack as your recursively parse the input, and then from the stack input into your linked list (sort of like how a RPN calculator would work).
Also add \n to your printf to make sure it is flushed to stdout:
printf("%s\n", node->data);

Resources