Building a binary tree given the postorder and inorder traversals - c

Following this link, I modified the code to build a binary tree given the postorder and inorder traversals. But the output seems to generate some junk values. I couldn't understand where I have gone wrong. A preorder traversal has root at the beginning and a postorder traversal has root at the end. Using that logic, I modified the code. As follows:
struct tree* buildTree2(char in[], char post[], int inStrt, int inEnd)
{
static int postIndex = sizeof(post)/sizeof(post[0]) - 1; //postorder index
if(inStrt > inEnd)
return NULL;
struct tree* tNode = newNode(post[postIndex--]);
if(inStrt == inEnd)
return tNode;
else
{
int inIndex = search(in, inStrt, inEnd, tNode->data);
tNode->left = buildTree(in, post, inStrt, inIndex-1);
tNode->right = buildTree(in, post, inIndex+1, inEnd);
return tNode;
}
}
Output:
The inorder traversal of the build tree (using preorder traversal) is : D B E A F C
The inorder traversal of the build tree (using postorder traversal) is : D B I R O 7 = R N T V _ G D X t u o . a / .
Modified code:
struct tree* buildTree2(char in[], char post[], int inStrt, int inEnd, int postIndex)
{
//printf("\n %d ",postIndex);
if(inStrt > inEnd) //termination condition for buildTree(in, post, inIndex+1, inEnd)
return NULL;
struct tree* tNode = newNode(post[postIndex--]);
//check if node has children
if(inStrt == inEnd)
return tNode;
else
{
//get the index of the postorder variable in the inorder traversal
int inIndex = search(in, inStrt, inEnd, tNode->data);
//Recursively build the tree
tNode->left = buildTree2(in, post, inStrt, inIndex-1, postIndex);
//The inIndex value points to the tNode. So less than that is left sub tree and more than that is the right sub tree
tNode->right = buildTree2(in, post, inIndex+1, inEnd, postIndex);
return tNode;
}
}
Output:
The inorder traversal of the build tree (using preorder traversal) is : D B E A F C
The inorder traversal of the build tree (using postorder traversal) is : E B E

node<int> * consTree(int * post, int * in, int postS, int postE, int inS, int inE){
if(postS > postE)
return NULL;
int rootdata = post[postE];
int indexI = -1;
for(int i = inS; i <= inE; i++){
if(rootdata == in[i]){
indexI = i;
break;
}
}
int lpostS = postS;
int linS = inS;
int linE = indexI - 1;
int lpostE = postS + indexI - inS - 1;
int rpostS = postS + indexI - inS;
int rpostE = postE - 1;
int rinS = indexI + 1;
int rinE = inE;
node<int> * root = new node<int>(rootdata);
root -> left = consTree(post,in,lpostS,lpostE,linS,linE);
root -> right = consTree(post,in,rpostS,rpostE,rinS,rinE);
return root;
}
Basically you need to think , when the right order both traversal are passed in the recursive call the array passed remain same just the indexes are changed..in that case let say i have pass in right order traversal (arr,6,9) so the changes should be made between that indexes only.. not from the 0(starting index of array)

Related

Binary search tree traversal in C

I have this function that traverses a binary search tree and appends nodes to a list if they are between a given lower and upper bound.
// n - the current node
// l - a list to accumulate results
static void doTreeSearchBetween(Tree t, Node n, Record lower,
Record upper, List l) {
// empty tree
if (n == NULL) {
return;
}
int cmpUpper = t->compare(n->rec, upper);
int cmpLower = t->compare(n->rec, lower);
// search left subtree
doTreeSearchBetween(t, n->left, lower, upper, l);
// if node if between lower and upper records append to list
if (cmpLower >= 0 && cmpUpper <= 0) {
ListAppend(l, n->rec);
}
// search right subtree
doTreeSearchBetween(t, n->right, lower, upper, l);
}
I realised the issue with this code is that it traverses the entirety of the list in-order, making it very inefficient and I'm looking for a way that would allow me to visit as few nodes as possible. The logic isn't working out for me, I was wondering if anyone had any ideas? I tried adding a couple if statements for whenever the current node is less than the lower and greater than the upper bound, that didn't work out for me.
An example of the output:
Inserting: 11 13 17 19 23 29 31 37 41 43
Searching between 10 and 20
Search returned: 11 13 17 19
Type defs:
typedef struct node *Node;
struct node {
Record rec;
Node left;
Node right;
};
struct tree {
Node root;
int (*compare)(Record, Record);
};
struct list {
Record *items;
int numItems;
int maxItems;
};
struct record {
char familyName[MAX_FAMILY_NAME_LENGTH + 1];
char givenName[MAX_GIVEN_NAME_LENGTH + 1];
};
You should rely on the comparisons to determine whether to recurse on the left and/or right branches:
if the tree node is below the lower bound, its left subtree can be pruned.
if the tree node is above the upper bound, its right subtree can be pruned.
Assuming it is empty at the root node, the list will be sorted by construction.
// n - the current node
// l - a list to accumulate results
static void doTreeSearchBetween(Tree t, Node n, Record lower,
Record upper, List l) {
// empty tree
if (n == NULL) {
return;
}
int cmpUpper = t->compare(n->rec, upper);
int cmpLower = t->compare(n->rec, lower);
if (cmpLower >= 0) {
// search left subtree
doTreeSearchBetween(t, n->left, lower, upper, l);
// if node if between lower and upper records append to list
if (cmpUpper <= 0) {
ListAppend(l, n->rec);
}
}
if (cmpUpper <= 0) {
// search right subtree
doTreeSearchBetween(t, n->right, lower, upper, l);
}
}

Combine like Polynomial Terms in stored in a linked list

I have a link list that each node stores the next node and the term. The term stores the coefficient, variable, and exponent. I need to iterate through the list and combine all like terms returning the first node with all others attached to it. I'm not even 100% sure if I am starting in the right place.
node_t * combine_like_terms(const node_t * current_node_ptr) {
if(current_node_ptr == NULL){
return NULL;
}
// node_t * start_node = current_node_ptr;
const node_t * curr = current_node_ptr;
node_t * newnodelist = NULL;
int maxexponent = 0;
do{
term_t *t = curr->term;
if(curr->term->exponent > maxexponent)
{
maxexponent = t->exponent;
}
}while((curr = curr->next_node));
puts("Max exp: \n");
curr = current_node_ptr;
for(int i = 0; i <= maxexponent; i++){
int coefficient = 0;
do{
term_t *x = curr->term;
if(x->exponent == i){
coefficient += x->coefficient;
}
}while((curr = curr->next_node));
term_t * terms = malloc(sizeof(term_t));
terms->coefficient = coefficient;
terms->var = 'x';
terms->exponent = i;
add_node(&newnodelist,terms);
}
return newnodelist;
}
due to some circumstances outside of my control the method return type and arguments can't be changed. My current idea is to find the highest exponent, then to go back through and find all coefficients with of each individual exponent and add them then add those new terms to a list. I am getting a segmentation fault before the puts("Max Exp: \n"); that I do not know that cause of.

How would you get a list of height unbalanced leaf nodes in a binary search tree?

To know whether a tree is height balanced or not we simply compare the height of left and right sub trees.
However, how do I create a program that will tell me how many nodes are unbalanced and print out those nodes?
As with all things trees: use recursion.
int num_unbalanced(node* root, int* height_out, int should_print) {
if (!root) { *height_out = 0; return 0; }
int left_height, right_height;
int left_unbalanced = num_unbalanced(root->left, &left_height, should_print);
int right_unbalanced = num_unbalanced(root->right, &right_height, should_print);
int this_unbalanced = abs(left_height - right_height) > 1;
*height_out = 1 + max(left_height, right_height);
if (should_print && this_unbalanced) print_node(root);
return left_unbalanced + right_unbalanced + this_unbalanced;
}

C Bubblesort in LinkedList

I'm trying to sort a doubly linked list, but I'm having some trouble. I'm a noob in C and I guess my problem is with pointers..
I just can't see how to swap two positions inside the list and so maybe that's the issue.
I tryied to sort it by using Bubblesort, even knowing that it's complexity is not so good because, how I'm still learning, thought that it was an easy way to start.
I also tryied reading some things about swaping elements in a linkedlist and how to sort them, but I'm really stuck with this problem...
PS: I started the for with the m->next cause my list has a header(m).
PS2:I'm getting the error "request for member ‘next’ in something not a structure or union", and don't know how to fix it
struct segment {
int x, y; /// position
char c; // letter
struct segment* next;
struct segment* prev;
};
void sortingSegments(struct segment* m) {
struct segment **j; struct segment **i;
for(i = &((m->next)->next); i !=NULL; i = i->next) {
for(j = &(m->next); j == i; j = j->next) {
if ((*j)->c > (*i)->c) {
struct segment **aux;
aux = i;
(*aux)->next = (*i)->next;
(*aux)->prev = (*i)->prev;
i = j;
(*i)->next = (*j)->next;
(*i)->prev = (*j)->prev;
j = aux;
(*j)->prev = (*aux)->prev;
(*j)->next = (*aux)->next;
}
}
}
}
Please read the comments and try to understand the linking of nodes.
It is based on the simple bubble sort described in wikipedia.
void sortingSegments(struct segment** m) {
struct segment *i, *tmp, *prev, *next;
int swapped = 1;
/*
* https://en.wikipedia.org/wiki/Bubble_sort#Pseudocode_implementation
* n = length(A)
* repeat
* swapped = false
* for i = 1 to n-1 inclusive do
* //if this pair is out of order
* if A[i - 1] > A[i] then
* // swap them and remember something changed
* swap(A[i - 1], A[i])
* swapped = true
* end if
* end for
* until not swapped
*/
// looping until no more swaps left
while (swapped) {
swapped = 0;
// we begin from the second item at each iteration
for (i = (*m)->next; i; i = i->next) {
// we need to swap i with i->prev
if (i->prev->c > i->c) {
prev = i->prev;
next = i->next;
// swapping first and second elements,
// so update m to reflect the change made
// to the head of the list
if (prev == *m) {
*m = i;
}
// so there is a prev of prev, update that two links
else {
prev->prev->next = i;
i->prev = prev->prev;
}
// so there is a next, update that two links
if (next) {
next->prev = prev;
prev->next = next;
}
// no next element, mark the end of the list
else {
prev->next = NULL;
}
// this is obvious, prev now becomes i's next
prev->prev = i;
i->next = prev;
// this is needed to reflect the change in i
i = prev;
swapped = 1;
}
}
}
}

a c program to add two singly linked lists, of unequal lengths containing single digited numbers in all of their nodes

i got this as an interview question. i was given 2 linked lists of unequal lengths,containing a single digited number in each of their nodes. i was asked to build a 3rd linked list which contains the sum of the two linked lists, again in the form of 1 digit in a node.
ex:
linked list 1 is
4-7-9-6
linked list 2 is
5-7
then the 3rd linked list would be
4-8-5-3
can someone suggest me an efficient algorithm, with minimum compromise in terms of space complexity?(i am not expecting an algo dat involves reversing the lists many times).
Reverse lists 1 and 2
Sum element-by-element (while
maintaining a carry), putting the
results in a list 3 that you
construct from tail to head
OR
Convert lists 1 and 2 to ints (e.g. int list1AsInt = 0; For each node {list1AsInt *= 10; list1AsInt += valueOfThisNode;} )
Sum those ints
Convert the result to a linked list (e.g. valueOfBrandNewNode = list3AsInt % 10; list3AsInt /= 10; Add a new node that points to the prev one; )
OR
Traverse both lists once to find out
their lengths. For this example,
let's assume that list 1 is longer
by N nodes.
Create a list 3 to represent the sum
without carries and a list 4 to
represent the carries.
For the first N nodes of list 1,
copy those values to list 3 and make
list 4's values be 0.
For the remaining nodes of lists 1
and 2, sum element-by-element,
putting the sum mod 10 in list 3 and
the carry in list 4. Keep track via
a bool of whether list 4 is all 0's.
Add a last node with value 0 to list
4.
If list 4 is entirely 0's, done.
Else, recurse to step 2,
treating list 3 as
the new list 1 and list 4 as the new
list 2. We know the length of the
new list 1 is the larger of the lengths
of the old lists 1 and 2, and the length
of the new list 2 is one more than that.
Read each digit as its ASCII equivalent into a char array indexed from 0, for both lists.
Use the atoi() function on both char arrays ( you may use atol() or atoll() if you are concerned about the length)
Add both numbers
Use the itoa() function to convert to a char array & then put back into new list.
Although, I admit the itoa() function is not standard.
If the lists are doubly linked it's easy:
Traverse both lists to the end.
Add the digits in corresponding nodes, and keep the carry digit.
Create the node in list 3.
Move one node towards the start of the lists and repeat.
The solution could be much simpler if the list stored the numbers in reverse order.
Nevertheless, with the given constraint, here is an approach.
find the nthToLast digit of both lists, starting with n = 0,
create a node with the sum of the digits,
update the (running) carry,
insert the newly created node at the head of the result list
Following is the (untested) C code.
typedef struct DigitNode_ {
int digit;
struct DigitNode_ * next;
} DigitNode;
/* Returns the n-th element from the end of the SLL;
if no such element exists, then return NULL.
See: https://stackoverflow.com/questions/2598348/
*/
extern DigitNode * nthNodeFromTail( DigitNode * listHead, size_t n );
/* Push pNode in the front, i.e. as the new head of the list */
extern void pushFront( DigitNode ** pListHead, DigitNode * pNode );
/* Create new list as sum of a and b, and return the head of the new list.
a -> 4 -> 7 -> 9 -> 6 -> NULL
b -> 5 -> 7 -> NULL
results in
c -> 4 -> 8 -> 5 -> 3 -> NULL
*/
DigitNode * sumDigitLists( DigitNode * a, DigitNode * b ) {
DigitNode * c = 0;
int carry = 0;
/* i is the position of a node from the tail of the list, backwards */
for( size_t i = 0; /* see 'break' inside */; i++ ) {
const DigitNode * const ithNodeA = nthNodeFromTail( a, i );
const DigitNode * const ithNodeB = nthNodeFromTail( b, i );
/* Stop when processing of both lists are finished */
if( !ithNodeA && !ithNodeB ) {
break;
}
const int ithDigitA = ithNodeA ? ithNodeA->digit : 0;
const int ithDigitB = ithNodeB ? ithNodeB->digit : 0;
assert( (0 <= ithDigitA) && (ithDigitA <= 9) );
assert( (0 <= ithDigitB) && (ithDigitB <= 9) );
const int conceptualIthDigitC = carry + ithDigitA + ithDigitB;
const int ithDigitC = conceptualIthDigitC % 10;
carry = conceptualIthDigitC / 10;
DigitNode ithNodeC = { ithDigitC, NULL };
pushFront( &c, &ithNodeC );
}
return c;
}
Take a look at this code:
node *add_two_linkedlist(node *head1,node *head2)
{
int i,j,temp;
node *p,*n;
p=head1;
n=head2;
i=count(head1);
j=count(head2);
if(i>j)
{
while(j!=0)
{
p->data=p->data+n->data;
if(p->data>10)
{
temp=(p->data)/10;
p->data=(p->data)%10;
p=p->next;
n=n->next;
p=p->data+temp;
j--;
}
}
return head1;
}
if(j>i)
{
while(i!=0)
{
n->data=p->data+n->data;
if(n->data>10)
{
temp=(n->data)/10;
n->data=(n->data)%10;
n=n->next;
p=p->next;
n=n->data+temp;
i--;
}
}
return head2;
}
}
This is straightforward. Assuming the leftmost node is the most significant bit. Align the two lists, add and propagate carry. Upon return create a new node if required..
#include <stdio.h>
struct list {
int val;
struct list * next;
};
int listadd (struct list *l1, struct list *l2) {
if ((l1 == NULL) || (l2 == NULL))
return;
int carry = 0;
if ((l1->next == NULL) && (l2->next != NULL)) {
carry += listadd (l1, l2->next) + l2->val;
return carry;
}
else if ((l1->next != NULL) && (l2->next == NULL)) {
carry +=listadd (l1->next, l2);
l1->val = l1->val + carry;
}
else if ((l1->next != NULL) && (l2->next != NULL)) {
carry += listadd (l1->next, l2->next);
}
else if ((l1->next == NULL) && (l2->next == NULL)) {
l1->val = l1->val + l2->val;
carry = l1->val/10;
l1->val = l1->val%10;
return carry;
}
carry = l1->val/10;
l1->val = l1->val%10;
return carry;
}
struct list * createnode (int val) {
struct list * temp = (struct list *) malloc (sizeof(struct list));
temp->val = val;
temp->next = NULL;
return temp;
}
int main() {
int carry = 0;
struct list *l1 = createnode(1);
l1->next = createnode(2);
struct list *l2 = createnode(7);
l2->next = createnode(8);
carry = listadd(l1,l2);
if (carry != 0) {
struct list * temp = createnode(carry);
temp->next = l1;
l1 = temp;
}
while (l1!= NULL) {
printf ("%d", l1->val);
l1=l1->next;
}
}

Resources