Printing in ascending order (sorting) from AVL trees - c

I need to define a main function that reads integers and prints them back in ascending order.
For example, if the input contains
12
4
19
6
the program should output
4
6
12
19
I need to use trees to do this however. I'm given the use of two functions insertavl, and deleteavlat my disposal. Their defintions are like so... http://ideone.com/8dwlU basically when deleteavl is called it deletes the node, and rebalances the tree accordingly
... If interested thier structures are in: http://ideone.com/QjlGe.
I've gotten this so far:
int main (void) {
int number;
struct node *t = NULL;
while (1 == scanf("%d",&number)) {
t = insertavl(t, number);
}
while (t != NULL){
printf("%d\n",t->data);
t = deleteavl(t, t->data);
}
}
But this doesn't print them in ascending order. Any suggestions would be helpful? thanks in advance!

Hint: in-order traversal on a BST is iterating the elements in ascending order.
Since an AVL Tree is a specific implementation of a BST, it also applies here.
EDIT: Explanation - why is this property of in-order traversal on a BST correct?
In in-order trvaersal, you access [print] each node after you accessed all the nodes in the left subtree. Since in a BST the root is bigger then all the nodes in the left subtree, it is what we wanted.
Also, in in-order traversal, you access each node before accessing all elements in the right sub-tree, and again, since it is a BST - this is exactly what we want.
(*)Note: This is not a formal proof, just an intuitive explanation why it is true.

Related

How can I construct a strict binary tree when the only information given is post order traversal?

Previously I asked how to get the pre-order of a tree when I am only given post-order traversal. However, now I'm curious as to how one would build a strict binary tree (strict binary tree meaning a node either has two children or no children) when only given post order traversal.
Some example data I am dealing with :
7 8 2 // 8,2 are dimensions stored in the node, likewise for other nodes)
6 4 8
3 1 5
A
B
I know what the tree is supposed to look like:
B
/ \
7 A
/ \
6 3
But I am lost on how to write a function that would actually build this tree (and store in the information in the nodes) from the information given (post order traveral.) How can I do this?
Creating a full binary tree from the postorder is like creating a syntax tree from Reverse Polish Notation with only binary operators. The branches are the operators, the leaves are the values. (You must be able to tell which is which. In your axample, brenches are letters, leaves are numbers.)
You can process the data as it comes. If it is a leaf, create a node and push it on the stack. It is is a branch, create a node, pop its right and left branches off the stack and push the new node. If the received data is valid, you should have a single node on the stack. That's the root of your tree.
So, in pseudo-ish C code:
Node *head = NULL;
while (!stream_empty()) {
int data = stream_get();
if (is_leaf(data)) {
if (nstack == MAX) fatal("Stack overflow!");
stack_push(make_node(data));
} else {
if (stack_size < 2) fatal("Stack underflow!");
Node *node = make_node(data);
node->right = stack_pop();
node->left = stack_pop();
stack_push(node);
}
}
if (nstack != 1) fatal("Ill-formed full binary tree!");
head = stack[0];
Stack overflow occurs when the tree is deeper than the stack size. Stack underflow or leftover nodes at the end occur when the input data is ill-formed.
Here's a full working example on ideone.
[Note: I've completely rewritten my answer, because the OP has specified new requirements. I had also based my original answer of a answer I gave to OP's previous question. I think that the present approach is more elegant. Whatever that means. :)]

Find maximum subtree in the given BST such that it has no duplicates

Given the BST which allows duplicates as separate vertices, how do I find the highest subtree such that it has no duplicates.
This is the idea:
(1) Check if the root value appears in its right subtree (inserting this way: left < root <= right). If not, tree has no duplicates. I look for it always on the left from the root's child.
(2) Traversing and doing (1) I can find all subtrees without duplicates, storing their root pointer and height.
(3) Comparing heights I can find largest seeked subtree.
I don't know how to store these information while traversing. I found programs for finding all duplicate subtrees of BST that use hash maps, but if possible I would prefer to avoid using hash maps, as I haven't had them on my course yet.
<!-- language: lang-c -->
typedef struct vertex {
int data;
struct vertex *left;
struct vertex *right;
} vertex, *pvertex;
// Utility functions
int Height(pvertex t){
if (t == NULL)
return 0;
if (Height(t->left) > Height(t->right))
return Height(t->left) + 1;
else
return Height(t->right) + 1;
}
int DoesItOccur(pvertex t, int k){
if(!t)
return 0;
if(t->data==k)
return 1;
if(t->data<k){
return DoesItOccur(t->left,k);
}
}
// My function
pvertex MaxSeeked(pvertex t){
if(!t)
return NULL;
if(DoesItOccur(t->right,t->data)==0)
return t;
else if{
if(t->left && t->right){
if(Height(MaxSeeked(t->left))>Height(MaxSeeked(t->right)))
return t->left;
else
return t->right;
}
}
else if{
......
}
}
I don't know how to store these information while traversing. I found programs for finding all duplicate subtrees of BST that use hash maps, but if possible I would prefer to avoid using hash maps, as I haven't had them on my course yet.
Note in the first place that you only need to track all the subtrees of the maximal height discovered so far. Or maybe you can limit that to just one such, if that's all you need to discover. For efficiency, you should also track what that maximal height actually is.
I'll suppose that you must not add members to your node structure, but if you could do, you could add a member or two wherein to record whether the tree rooted at each node contains any dupes, and how high that tree is. You could populate those data as you go, and remember what the maximum height is, then make a second traversal to collect the nodes.
But without modifying any nodes themselves, you can still track the current candidates by other means, such as a linked list. And you can put whatever metadata you want into the tracking data structure. For example,
struct nondupe_subtree {
struct vertex *root;
int height;
struct nondupe_subtree *next;
};
You can then, say, perform a selective traversal of your tree in breadth first order, carrying along a linked list of struct nondupe_subtree nodes:
Start by visiting the root node.
Test the subtree rooted at each visited node to see whether it contains any dupes, according to the procedure you have described.
If so then enqueue its children for traversal.
If not then measure the subtree height and update your linked list (or not) accordingly. Do not enqueue this node's children.
When no more nodes are enqueued for traversal, you linked list contains the roots of all the maximal height subtrees without dupes.
Note that that algorithm would in many cases be significantly sped if you could compute and store all the subtree heights in an initial DFS pass, for it is otherwise prone to performing duplicate tree-height computations. Many of them, in some cases.
Note also that although it does simplify this particular algorithm, your rule for always putting dupes to the right works against balanced trees, which may also yield reduced performance. In the worst case, where are vertices are duplicate, your "tree" will perforce be linear.

Should Binary Heap be a binary tree or linked list?

I have an assignment to implement a binary heap. However, I'm not sure whether I should implement the binary heap as a binary tree data structure or a simple double linked list.
If I should implement as a binary tree, how should I keep track of the last element of the tree in order to insert a new element? In linked list that would be much easier.
So, does binary heap have to be a binary tree? If yes, how to track the last element?
Note: In my assignment there is a statement like this:
But you will implement the binary heap not as an array, but
as a tree.
To be more clear this is my node:
struct Word{
char * word;
int count;
struct Word * parent;
struct Word * left_child;
struct Word * right_child;
}
Solution taken from the question.
by #Yunus Eren Güzel
SOLVED:
After five hours of study I have found a way to implement heap as a pointer based tree.
The insertion algorithm is :
insert
node = create_a_node
parent = get_the_last_parent
node->parent = parent
if parent->left==NULL
parent->left=node
else
parent->right=node
end insert
get_last_parent parent,&height
height++
if parent->left==NULL || parent->right==NULL
return parent;
else
int left_height=0,right_height=0;
left = get_last_parent(parent->left,&left_height)
right = get_last_parent(parent->right,&right_height)
if left_height == right_height
height += right_height
return right
else if left_height > right_height
height += left_height
return left
end get_last_parent
A binary heap is, by definition, a binary tree. One way of implementing this in C is to store the tree elements in an array where the array index corresponds to the tree element (numbering the root node 0, its left child 1, its right child 2, and so on). You can then just store the size of the heap (initialized to 0 upon creation and incremented whenever an element is added) and use that to find the next open location.
For basic data structures questions like this, Wikipedia is your friend.
You should implement it as a tree. It will be easy and interesting. Heap has only property that any node has value less than or equal to its parent, if it is a max heap.
In array implementation we impose some more conditions.
If you need help about specific function implementation then you can ask it.
You need to travel down to add new node
call it with root, value to be inserted
insert(node, x){
if(node->value >= x)
//insert
if(node->left == 0)
node->left = new Node(x);
else if(node->right == 0)
node->right = new Node(x);
else if(node->left->value >= x)
insert(node->left, x);
else if(node->right->value >= x)
insert(node->right, x);
else
//insert between node and its any one child
insertBW(node, node->left, x);
else //if x is less than node value
//insert between node and its parent
insertBW(node->parent, node, x)
}
insertBW(p, c) is a function which insets a node containing value x between p and c
(I didn't tested this code please check for errors)
insertBW(Node* p, Node* c, T x)
{
Node* newnode = new Node(x);
newNode.x = x;
if(p == 0) //if node c is root
{
newnode.left = Tree.root.left;
Tree.root = newnode;
}
else
{
newnode.parent = p;
newnode.child = c;
if(p.left == c)
{
p.left = newnode;
}
else p.right = newnode;
}
}
This to me really seems to be a homework question & it seems you have not done any R&D on your own before asking (sorry for bit harsh words):)
In computer science, a heap is a specialized tree-based data structure that satisfies the heap property: if B is a child node of A, then key(A) ≥ key(B).
I think your teacher wants you to implement a priority queue data structure and that's where you are talking about both a Linked List and Heap together in the same question. Priority Queue can be implemented as a Heap or a Linked List where in to extract elements based on priority either you have to maintain elements sorted in case of linked list where say a maximum or minimum element goes at the front based upon whether you are implementing a max heap or a min heap OR priority queue can be implemented simply as a heap data structure.
Coming to the last point where you say "But you will implement the binary heap not as an array, but as a tree.", seems to be very irrelevant. Please do check again as to what is required or reproduce the exact question that has been asked in your assignment.
To put it simply, regarding your first question - no. A heap can be anything (array, linked list, tree, and when one must improvise a family of fluffy kittens). Note the definition of a heap: If "B" is a child of "A" then val(A) >= val(B) (or, in case of a min-heap, val(A) <= val(B)).
It's most common to refer to it as a tree (and also implement it as such) because it's easy to think of it as a tree. Also, the time-complexity & performance are good.
Regarding your second question, you gave no information, so as far as I know a solution that searches every node is as good as any other...
For any better answer, more information is required (what limitations do you have, what operations should you support, etc...)
A binary heap can be anything i.e. array, linked list, tree, etc. We just have to keep the right algorithm on how can you can access the data. For example, if you want to make it to the left child you can do this by 2N + 1(For starting index 0) where N is the parent index or the right child by 2N + 2. For the last element, you can initialise the heap with a variable count and increment it by 1 every time you insert a new element, this way you can keep track of the last element (Same for delete, just some modification has to be made on the collection).

convert Binary tree to Binary Search Tree inplace using C

Without using any extra space convert Binary Tree to Binary Search tree.I came up with the following algo but It doesn't work.
BTtoBST(node *root)
1.if the root is NULL return
2.else current=root
3.if (current->left > current) swap(current->left , current)
4.if (current->right < current) swap(current->right , current)
5.current=current->left
6 go to 3 if current!=NULL else go to 4
7.current=current->right
Thanks in advance
PS:I saw this link but was not of much help!!
Convert Binary Tree -> BST (maintaining original tree shape)
You can swap the nodes including subtrees (not only the node content) like in an AVL Tree http://en.wikipedia.org/wiki/AVL_tree
Just keep swapping as long as BST constraints are violated, restarting deep first search from root after each swap.
Perform a post-order (bottom up) traversal of the tree, taking the nodes that are visited and inserting them into a BST.
Does "without any extra space" preclude recursion?
If not, then something like:
# top level call passes null for bst
bt_to_bst (root, bst)
# nothing to add to bst; just return it
if null(root) -> return bst
# if this is a leaf node, stick it into the BST
if null(root->left) && null(root->right)
return bst_insert(bst, root)
# otherwise add all of left subtree into the bst and then the right tree
bst = bt_to_bst (root->left, bst);
return bt_to_bst (root->right, bst);
bt_to_bst is a filtering operation; it takes an existing bst and returns a new one with the given node added to it.
Adding a leaf node to the bst is safe because we will never visit it again, so we can overwrite its left and right pointers.

compare nodes of a binary tree

If I have two binary trees, how would I check if the elements in all the nodes are equal.
Any ideas on how to solve this problem?
You would do a parallel tree traversal - choose your order (pre-order, post-order, in-order). If at any time the values stored in the current nodes differ, so do the two trees. If one left node is null and the other isn't, the trees are different; ditto for right nodes.
Does node order matters? I'm assuming for this answer that the two following trees :
1 1
/ \ / \
3 2 2 3
are not equal, because node position and order is taken into account for the comparison.
A few hints
Do you agree that two empty trees are equal?
Do you agree that two trees that only have a root node, with identical node values, are equal?
Can't you generalize this approach?
Being a bit more precise
Consider this generic tree:
rootnode(value=V)
/ \
/ \
-------- -------
| left | | right |
| subtree| |subtree|
-------- -------
rootnode is a single node. The two children are more generic, and represent binary trees. The children can either be empty, or a single node, or a fully-grown binary tree.
Do you agree that this representation is generic enough to represent any kind of non-empty binary tree? Are you able to decompose, say, this simple tree into my representation?
If you understand this concept, then this decomposition can help you to solve the problem. If you do understand the concept, but can't go any further with the algorithm, please comment here and I'll be a bit more specific :)
you could use something like Tree Traversal to check each value.
If the trees are binary search trees, so that a pre-order walk will produce a reliable, repeatable ordering of items, the existing answers will work. If they're arbitrary binary trees, you have a much more interesting problem, and should look into hash tables.
My solution would be to flatten the two trees into 2 arrays (using level order), and then iterate through each item and compare. You know both arrays are the same order. You can do simple pre-checks such as if the array sizes differ then the two trees aren't the same.
Level Order is fairly easy to implement, the Wikipedia article on tree traversal basically gives you everything you need, including code. If efficiency is being asked for in the question, then a non-recursive solution is best, and done using a FIFO list (a Queue in C# parlance - I'm not a C programmer).
Let the two tree pass through same tree traversal logic and match the outputs. If even a single node data does not match the trees dont match.
Or you could just create a simple tree traversal logic and compare the node values at each recursion.
You can use pointers and recursion to check if node is equal, then check subtrees. The code can be writen as following in Java language.
public boolean sameTree(Node root1, Node root2){
//base case :both are empty
if(root1==null && root2==null )
return true;
if(root1.equals(root2)) {
//subtrees
boolean left=sameTree(root1.left,root2.left);
boolean right=sameTree(root1.right,root2.right);
return (left && right);
}//end if
else{
return false;
}//end else
}//end sameTree()
Writing a C code as a tag mentions in the question.
int is_same(node* T1,node* T2)
{
if(!T1 && !T2)
return 1;
if(!T1 || !T2)
return 0;
if(T1->data == T2->data)
{
int left = is_same(T1->left,T2->left);
int right = is_same(T1->right,T2->right);
return (left && right);
}
else
return 0;
}
Takes care of structure as well as values.
One line code is enough to check if two binary tree node are equal (same value and same structure) or not.
bool isEqual(BinaryTreeNode *a, BinaryTreeNode *b)
{
return (a && b) ? (a->m_nValue==b->m_nValue && isEqual(a->m_pLeft,b->m_pLeft) && isEqual(a->m_pRight,b->m_pRight)) : (a == b);
}
If your values are numerical int, in a known range, you can use an array, (let's say max value n). Traverse through the 1st tree using whatever method you want, adding the data into a said array, in an appropriate index (using the node data as index). Then, traverse through the second tree and check for every node in it, if array[node.data] is not null. If not - trees are identical.
**assuming for each tree all nodes are unique

Resources