Search function for a tree - c

I am working with a ternary search tree. Following code should give you an overview of how the tree looks like. Every leaf will contain a pointer to a linked list which contains pointer to the head node. Every leaf can have at most 3 nodes. Therefore after the root leaf has been filled with 3 data values the next value if it is smaller than the first node will get inserted in to the left if it is greater it gets inserted in to the right and if it is in the middle it will get inserted in to the centre child.
struct data
{
int val;
};
struct node
{
struct node* next;
struct data* dta;
};
struct linkedList
{
int size;
struct node *head;
};
struct leaf
{
struct linkedList* ll;
struct leaf* left;
struct leaf* right;
struct leaf* center;
struct leaf* parent;
};
struct tree
{
struct leaf* root;
};
I am currently trying to create a function that takes in a tree and a int value as inputs. Then it checks every leaf in the tree to see if some leaf equals the int value and if it does it will return 1 and 0 otherwise.
Following is my code
int totalLeaf(struct leaf *lf)
{
int sum = 0;
struct node *temp = lf->ll->head;
while(temp!=NULL)
{
sum = sum + temp->dta->val;
temp = temp->next;
}
printf("sum is : %d\n",sum);
return sum;
}
int searchTotal(struct tree *tr,int total)
{
if(tr->root == NULL)
{
return 0;
}
else
{
return searchTotal_r(tr->root,total);
}
}
int searchTotal_r(struct leaf *lf,int total)
{
if(lf==NULL)
{
return 0;
}
if(totalLeaf(lf) == total)
{
return 1;
}
else
{
searchTotal_r(lf->left,total);
searchTotal_r(lf->center,total);
searchTotal_r(lf->right,total);
}
return 0;
}
Can anyone suggest where i have gone wrong and how i can fix this issue?

else
{
searchTotal_r(lf->left,total);
searchTotal_r(lf->center,total);
searchTotal_r(lf->right,total);
}
Change to:
else
{
return searchTotal_r(lf->left,total) ||
searchTotal_r(lf->center,total) ||
searchTotal_r(lf->right,total);
}
The way you currently have it, the recursive searches don't actually matter because you always return 0 even if you find something.

Related

binaryTree insert and remove - C

I have done insert a node and delete a tree with a tutorial. I test it and it works fine. However I can't understand why I need to pass by reference the root in insert, but in deleteAll just the pointer. Because I think that passing just the pointer its a value reference and then every change is only seen in the function.
typedef struct node{
int element;
struct node *left;
struct node *right;
}*tTree;
void insert(tTree *myTree, int element){
if(*myTree == NULL){
myTree= (tTree)malloc(sizeof(*myTree));
myTree->element = element;
myTree->left = NULL;
myTree->right = NULL;
}
else{
int treeElement = (*myTree)->element;
if( treeElement > element){
insert(&(*myTree)->left, element);
}
else{
insert(&(*myTree)->right, element);
}
}
}
void deleteAll(tTree myTree){
if(myTree != NULL){
deleteAll(myTree->right);
deleteAll(myTree->left);
free(myTree);
}
}
int size(tTree myTree){
if (myTree != NULL){
return 1 + size(myTree->right) + size(myTree->left);
}
else
return 0;
}
int main(){
tTree root = NULL;
insert(&root,3);
insert(&root,2);
insert(&root,4);
insert(&root,1);
printf("Number of nodes: %d\n",size(root));
deleteAll(root);
root = NULL;
printf("Number of nodes: %d\n",size(root));
return 1;
}
The deletion needs only the pointer for the statements it executes. It is not passing any information back to the calling function. However, your insertion function allocates if needed, and in that case must pass back the allocated pointer to the caller.

recursive function that tells if a Tree is a Binary Search Tree ( BST ) (Modified code)

I was working on the exercises here :
"http://cslibrary.stanford.edu/110/BinaryTrees.html#s2"
I wrote a function that decides if a Tree is a BST(return 1) or not(return 0) but I'm not sure if my code is totally good, I tested it for a BST and a non-BST Tree and it seems to work correctly. I want to know the opinion of the community :
Updated Code :
consider the Tree ( not a BST ) :
5
/ \
2 7
/ \
1 6
my Idea is to compare 2 with 5 if it's good, then 1 with 5, and if it's good then 6 with 5 if it's good then 1 with 2 if it's good then 6 with 2 if it's good then 5 with 7 ; if it's good isBST() returns 1. this code is supposed to do it recursively.
the node structure :
struct node {
int data;
struct node* left;
struct node* right;
};
the code :
int lisgood(struct node* n1,struct node* n2)
{
if(n2 == NULL)
return 1;
else{
int r = lisgood(n1,n2->left)*lisgood(n1,n2->right);
if(r){
if(n1->data >= n2->data)
{
return r;
}
else return 0;
}
else return r;
}
}
int risgood(struct node* n1,struct node* n2)
{
if(n2 == NULL)
return 1;
else{
int r = risgood(n1,n2->right)*risgood(n1,n2->left);
if(r){
if(n1->data < n2->data)
{
return r;
}
else return 0;
}
else return r;
}
}
int isBST(struct node* node)
{
if(node == NULL)
return 1;
else{
if(lisgood(node,node->left)&&risgood(node,node->right)){
return (isBST(node->left)&&isBST(node->right));
}
else return 0;
}
}
Your code doesn't really work - not even for the example you showed. You never compare 5 to 6. Basically you are comparing the root of a sub-tree with root->left, root->left->left, root->left->left->left, etc. Then you are comparing root with root->right, root->right->right, etc., but you never compare root with the other nodes in the subtree. The problem is that you don't compare a tree's root with every element on its right and left subtrees, and you should.
This is a known interview question. The simpler way to solve it is to pass in the minimum and maximum values allowed for a sub-tree as parameters.
Here's how it works with the example tree you showed: you see 5, thus, the maximum value for any node on 5's left subtree is 5. Similarly, the minimum value for any node on 5's right subtree is 5. This property is applied recursively to check that every node's value is consistent with the requirements. Here's a working implementation (assumes a tree with no duplicates):
#include <stdio.h>
#include <limits.h>
struct tree_node {
int key;
struct tree_node *left;
struct tree_node *right;
};
static int is_bst_aux(struct tree_node *root, int min, int max) {
if (root == NULL) {
return 1;
}
if (!(min < root->key && root->key < max)) {
return 0;
}
if (!is_bst_aux(root->left, min, root->key)) {
return 0;
}
return is_bst_aux(root->right, root->key, max);
}
int is_bst(struct tree_node *root) {
return is_bst_aux(root, INT_MIN, INT_MAX);
}

insertion binary search tree in C

I've been stuck on the insertion part of the binary search tree. I get so confused with nested structs. The basic idea of this program is to create a bst that is able to hold names and double values which get stored by value (obviously).
Example: I want to store
Jane 3.14
John 3.233
Luke 6.4
Mike 1.4
so the bst would look like
3.14
/ \
1.4 3.233
\
6.4
however I'm having trouble with the insertHelper recursion portion of the code. The hash table is a bonus part of the code that I'll try implementing at a later time. Thank you for your help!
typedef struct name_val // holds name and value
{
char *name;
double value;
}NAME_VAL;
typedef struct node //binary search tree
{
NAME_VAL *nV;
struct node *left;
struct node *right;
}NODE;
struct tmap_struct //handle for bst and hashtable
{
int nL; //nodes on left
int nR; //nodes on right
NODE *root;
NODE **table;
};
int tmap_insert(TMAP_PTR hashTree, char * name, double val)
{
if(hashTree->root == NULL)
{
NODE *bst = (NODE *)malloc(sizeof(NODE));
NAME_VAL *root = (NAME_VAL *)malloc(sizeof(NAME_VAL));
bst->nV = root;
bst->nV->value = val;
strcpy(bst->nV->name, name);
hashTree->root = bst;
hashTree->nL = 0;
hashTree->nR = 0;
}
else
insertHelper(hashTree->root, val, name);
}
void insertHelper(TMAP_PTR hashTree, int val, char * name)
{
if(val < hashTree->root->nV->value)
{
if(hashTree->root->left == NULL)
{
hashTree->root->left = (NODE *)malloc(sizeof(NODE));
hashTree->root->left->nV = (NAME_VAL *) malloc(sizeof(NAME_VAL));
strcpy(hashTree->root->left->nV->name, name);
hashTree->root->nV->value = val;
(hashTree->nL)++;
}
else
insertHelper(hashTree->root->left, val, name);
}
else
{
if(hashTree->root->right == NULL)
{
hashTree->root->right = (NODE *)malloc(sizeof(NODE));
hashTree->root->right->nV = (NAME_VAL *)malloc(sizeof(NAME_VAL));
strcpy(hashTree->root->left->nV->name,name);
hashTree->root->nV->value = val;
(hashTree->nR)++;
}
else
insertHelper(hashTree->root->right, val, name);
}
}
I doubt this compiles. Is that the problem you're having?
From what I can see, you have declared insertHelper with the wrong type for its first parameter. It should take NODE* values, not TMAP_PTR values. That's because you always call it with nodes out of your tree.
So the first part of the function should look like this:
void insertHelper(NODE *node, int val, char * name)
{
if(val < node->nV->value)
{
if(node->left == NULL)
{
node->left = (NODE *)malloc(sizeof(NODE));
node->left->nV = (NAME_VAL *) malloc(sizeof(NAME_VAL));
strcpy(node->left->nV->name, name);
node->left->nV->value = val;
}
else
insertHelper(node->left, val, name);
}
//.....
Note that I removed the line:
(hashTree->nR)++;
It hardly even makes sense to track this information, unless maybe you do it at the node level.
But if you must, you could have insertHelper recursively return a positive or negative value to indicate what side it inserted on. But that doesn't makes sense. What is it on the right of? You may have inserted it on the right of a node that was in the left half of the tree.
If you store this information on each node, you can recursively update the node above as you return from insertHelper. Maybe that's what you were trying to do. Balanced tree implementations do something similar - AVL trees store the maximum depth of the tree at a node and use that to do branch rotations for rebalancing.
You'll have to adapt mine(It's almost standard C besides the unneeded template and class), but it's a similar algorithm: (I believe, I didn't look at any source for my own purposes.)
template<typename T>
class BST {
protected:
typedef struct node_t {
struct node_t * dir[2];
T data;
} node;
node * root;
void insert_node(node * active_node, T data){ //call with node *root;
int next = data < active_node->data ? 0 : 1;
if(active_node->dir[next] == NULL){
active_node->dir[next] = new node;
active_node->dir[next]->dir[0] = NULL;
active_node->dir[next]->dir[1] = NULL;
active_node->data = data;
} else
insert_node(active_node->dir[next], data);
}
public:
BST() : root(new node){root->dir[0] = NULL; root->dir[1] = NULL; root->data = 0;}
~BST(){}
}

Adding nodes to Binary Search Tree

Disclaimer: This is for an assignment. I am not asking for explicit code answers, only help understanding why my code isn't working.
I am trying to implement a basic Binary Search Tree, but I am having problems with my _addNode(...) function.
Here's the problem. When I walk through my code with the debugger, I notice that leaf nodes are created infinitely on both sides (left and right) so aside from the creation of the root, there is never any point when a leaf node is NULL. The problem is that I am asking my program to create a new node whenever it finds a NULL value where a leaf would be. Therefore, if there are never any NULL values, there will never be any new leaves created, right?
The other issue I'm running into is with my compare(...) function. Stepping through it in the debugger shows it to iterate through the function several times, never actually returning a value. When it returns to the calling function, it drops back into the compare(...) function and loops infinitely. Again, I don't know why this is happening considering I have valid return statements in each if statement.
Here is all the code you'll probably need. If I left something out, let me know and I'll post it.
struct Node {
TYPE val;
struct Node *left;
struct Node *right;
};
struct BSTree {
struct Node *root;
int cnt;
};
struct data {
int number;
char *name;
};
int compare(TYPE left, TYPE right)
{
assert(left != 0);
assert(right != 0);
struct data *leftData = (struct data *) left;
struct data *rightData = (struct data *) right;
if (leftData->number < rightData->number) {
return -1;
}
if (leftData->number > rightData->number) {
return 1;
} else return 0;
}
void addBSTree(struct BSTree *tree, TYPE val)
{
tree->root = _addNode(tree->root, val);
tree->cnt++;
}
struct Node *_addNode(struct Node *cur, TYPE val)
{
assert(val != 0);
if(cur == NULL) {
struct Node * newNode = malloc(sizeof(struct Node));
newNode->val = val;
return newNode;
}
if (compare(val, cur->val) == -1) {
//(val < cur->val)
cur->left = _addNode(cur->left, val);
} else cur->right = _addNode(cur->right, val);
return cur;
}
Edit: Adding the below function(s)
int main(int argc, char *argv[])
{
struct BSTree *tree = newBSTree();
/*Create value of the type of data that you want to store*/
struct data myData1;
struct data myData2;
struct data myData3;
struct data myData4;
myData1.number = 5;
myData1.name = "rooty";
myData2.number = 1;
myData2.name = "lefty";
myData3.number = 10;
myData3.name = "righty";
myData4.number = 3;
myData4.name = "righty";
/*add the values to BST*/
addBSTree(tree, &myData1);
addBSTree(tree, &myData2);
addBSTree(tree, &myData3);
addBSTree(tree, &myData4);
/*Print the entire tree*/
printTree(tree);
/*(( 1 ( 3 ) ) 5 ( 10 ))*/
return 1;
}
Maybe you could try setting right and left to NULL right after malloc:
struct Node * newNode = malloc(sizeof(struct Node));
newNode->left = NULL;
newNode->right = NULL;
Check this line here (or the corresponding for left):
cur->right = _addNode(cur->right, val);
If cur->right == 0, it's fine. But if cur->right != 0, the node that was sitting there will be replaced by the return value of _addNode, which ultimately is not a whole branch, but just one node.
I like to explicitly 0-out values in a struct after a malloc using memset(newNode, 0, sizeof(struct Node)). Others might disagree.

Error in trying to count the nodes in circular doubly linked list recursively

Here is my implementation of count:
int count(node *start)
{
static int l ;
node *current; /* Node for travelling the linked list*/
current=start;
if(current->next!=start)
{
l = 1 + count ( current->next ) ;
return ( l ) ;
}
else
{
return(1);
}
}
Here is a fragment of main function where I am calling it:
void main()
{
node *head;
printf ( "Length of linked list = %d", count ( head ) ) ;
}
Here is the structure:
struct cirdoublelinklist
{
struct cirdoublelinklist *prev; /** Stores address of previous node **/
int value; /** stores value **/
struct cirdoublelinklist *next; /** stores address of next node **/
};
/** Redefining list as node **/
typedef struct cirdoublelinklist node;
On running and trying to see the length of a list, it crashes with out of bound memory. Please help me with this, I have been working on this for a long time now.
Method to add the first node:
void initialize(node *start)
{
start->prev=start;
printf("\nEnter Value\n");
scanf("%d",&start->value);
start->next=start;
}
Method to add subsequent nodes after the location specified:
void insert_after(node *start)
{
int num; /* value for inserting a node */
int flag=0;
node *newnode; /* New inputed node*/
node *current; /* Node for travelling the linked list*/
newnode=(node*)malloc(sizeof(node));
printf("\nEnter the value after which you want to insert a node\n");
scanf("%d",&num);
init(newnode);
current=start;
while(current->next!=start)
{
if(current->value==num)
{
newnode->next=current->next;
current->next->prev=newnode;
current->next=newnode;
newnode->prev=current;
flag=1;
}
current=current->next;
}
if(flag==0 && current->next==start && current->value==num)
{
/*** Insertion checking for last node ***/
newnode->next=current->next; /* Start is being copied */
current->next->prev=newnode;
current->next=newnode;
newnode->prev=current;
flag=1;
}
if(flag==0 && current->next==NULL)
printf("\nNo match found\n");
}
Every time you call count, it has a new start, so current->next!=start is always comparing a node to its successor, which will only ever end if the list has length 1. What you most likely want to do is have two functions:
int count(node *start)
{
if(start == NULL)
return 0;
return count_helper(start, start);
}
int count_helper(node *start, node *current)
{
static int l;
if(current->next!=start)
{
l = 1 + count (start, current->next);
return ( l ) ;
}
else
{
return(1);
}
}
As others have mentioned, the static variable is not necessary. A better way of writing what I have called count_helper would be:
int count_helper(node *start, node *current)
{
if(current->next!=start)
{
return 1 + count (start, current->next);
}
else
{
return 1;
}
}
Finally, a more efficient implementation would be non-recursive:
int count(node *start)
{
if(start == NULL)
return 0;
node *current = start->next;
int c = 1;
while(current != start)
{
c++;
current = current->next;
}
return c;
}
Well, the problem is that you call the function in the main on a NULL pointer. Infact node *head; is declared but never assigned to something. So when you execute this line:
if(current->next!=start)
the program crashes because it will check for NULL->next that, obviously, doesn't exist.
You need to pass a pointer to start pointer in insert_after function
void insert_after(node **start)
instead of
void insert_after(node *start)
Otherwise you'll be just updating the local copy of *start.
Similarly for initialize
void initialize(node **start)
Put simply, the recursive calls don't know the original start node. You will need to add a second node* argument and pass the start node via it.
Here's a recursive solution that doesn't use static or helper variables:
int count(Node* head) {
// Base cases:
// 0 nodes
if (!head)
return 0;
// 1 node
if (head->next == next)
return 1;
// Keep a pointer to the node to be removed
Node* rest = head->next;
// Remove the node
head->next = head->next->next;
// Get the length of the new list
int result = 1 + count(head->next);
// Reconnect the node
head->next = rest;
return result;
}

Resources