How to insert a node in BST using iterative method? - binary-search-tree

This it what i tried to implement
struct bstnode* insert(struct bstnode* root, int data){
struct bstnode* temp = getnewnode(data);
struct bstnode* temp1=root;
while(1){
if(temp1 == NULL){
temp1 = temp;
if(root == NULL) root = temp;
return root;
}
else if(data<=temp1->data)
temp1 = temp1->left;
else
temp1 = temp1->right;
}
}
what's wrong with this solution. I have tried to make link of new node to its desirable position by traversing

To create a BST, the new node temp shall be attached to left branch as temp1->left = temp; or to right branch as temp1->right = temp;.
Step 1 - before search to the left branch, check if NULL and assign the new node.
else if(data<=temp1->data) {
// check the left node
if (temp1->left==NULL) {
// attach the new node to left
temp1->left = temp;
return (root);
}
// otherwise continue
temp1 = temp1->left;
}
Instead of:
else if(data<=temp1->data)
temp1 = temp1->left;
Step 2 - same check for the right branch.
else {
// check the right node
if (temp1->right==NULL) {
// attach the new node to right
temp1->right = temp;
return (root);
}
// otherwise continue
temp1 = temp1->right;
}
Instead of:
else
temp1 = temp1->right;

Related

How to make a report parameter selection change another report parameter selection values while allowing multiselect for both of them?

Lets say I have a table with a list of names, such as "a, b, c" and each name has several other values assigned (some of the other values can be assigned to several/all of names values, example below).
Table example:
( names - other ):
a - aa
a - ab
a - ac
b - ab
b - bb
b - cb
c - ac
c - bc
c - cc
How do I make in birt so that I could select names in one parameter box and get corresponding other values to select for another parameter? I know it's possible to do that with cascading parameter, but that doesn't allow to have multiselect for the first parameter, which in our example would be names values.
Found a solution partly here: https://forums.opentext.com/forums/developer/discussion/61283/allow-multi-value-for-cascading-parameter
and here (thanks google translate ^^): https://www.developpez.net/forums/d1402270/logiciels/solutions-d-entreprise/business-intelligence/birt/birt-4-3-1-multi-value-cascade-parameters/
Steps to do:
change"\birt\webcontent\birt\ajax\ui\dialog\BirtParameterDialog.js" file contents (there is a file to download for replacement in one of the links, but in case it goes dead I'm sharing 2 snippets from it where the changes occur:
__refresh_cascade_select : function( element )
{
var matrix = new Array( );
var m = 0;
for( var i = 0; i < this.__cascadingParameter.length; i++ )
{
for( var j = 0; j < this.__cascadingParameter[i].length; j++ )
{
var paramName = this.__cascadingParameter[i][j].name;
if( paramName == this.__isnull )
paramName = this.__cascadingParameter[i][j].value;
if( paramName == element.id.substr( 0, element.id.length - 10 ) )
{
//CHANGE//
//The two way work (String(selectedValue) or Array(SelectedValueArray))
var l = 0;
var isFirstElement = true;
var selectedValue = "";
var selectedValueArray = new Array();
for(var test = 0; test<element.options.length;test++){
if(element.options[test].selected){
if(isFirstElement){
isFirstElement = false;
selectedValue = element.options[test].value;
}
else{
selectedValue = selectedValue+","+element.options[test].value;
}
selectedValueArray[l] = element.options[test].value;
l++;
}
}
//CHANGE//
var tempText = element.options[element.selectedIndex].text;
var tempValue = element.options[element.selectedIndex].value;
// Null Value Parameter
if ( tempValue == Constants.nullValue )
{
this.__cascadingParameter[i][j].name = this.__isnull;
this.__cascadingParameter[i][j].value = paramName;
}
else if( tempValue == '' )
{
if( tempText == "" )
{
var target = element;
target = target.parentNode;
var oInputs = target.getElementsByTagName( "input" );
if( oInputs.length >0 && oInputs[1].value != Constants.TYPE_STRING )
{
// Only String parameter allows blank value
alert( birtUtility.formatMessage( Constants.error.parameterNotAllowBlank, paramName ) );
this.__clearSubCascadingParameter( this.__cascadingParameter[i], j );
return;
}
else
{
// Blank Value
this.__cascadingParameter[i][j].name = paramName;
this.__cascadingParameter[i][j].value = tempValue;
}
}
else
{
// Blank Value
this.__cascadingParameter[i][j].name = paramName;
this.__cascadingParameter[i][j].value = tempValue;
}
}
else
{
this.__cascadingParameter[i][j].name = paramName;
//CHANGE//
//The two way work (String(selectedValue) or Array(SelectedValueArray))
this.__cascadingParameter[i][j].value = selectedValueArray;
//CHANGE//
}
for( var m = 0; m <= j; m++ )
{
if( !matrix[m] )
{
matrix[m] = {};
}
matrix[m].name = this.__cascadingParameter[i][m].name;
matrix[m].value = this.__cascadingParameter[i][m].value;
}
this.__pendingCascadingCalls++;
birtEventDispatcher.broadcastEvent( birtEvent.__E_CASCADING_PARAMETER, matrix );
}
}
}
},
and this:
// exist select control and input text/password
// compare the parent div offsetTop
if( oFirstITC.parentNode && oFirstST.parentNode )
{
// Bugzilla 265615: need to use cumulative offset for special cases
// where one element is inside a group container
var offsetITC = Position.cumulativeOffset( oFirstITC );
var offsetST = Position.cumulativeOffset( oFirstST );
// compare y-offset first, then x-offset to determine the visual order
if( ( offsetITC[1] > offsetST[1] ) || ( offsetITC[1] == offsetST[1] && offsetITC[0] > offsetST[0] ) )
{
oFirstST.focus( );
}
else
{
oFirstITC.focus( );
}
}
After .js is changed cascading parameters can have multiselect on all levels.
Example:
1st DataSet "DS_country" query:
select CLASSICMODELS.OFFICES.COUNTRY
from CLASSICMODELS.OFFICES
2nd DataSet "DS_office" query:
select CLASSICMODELS.OFFICES.OFFICECODE
from CLASSICMODELS.OFFICES
where CLASSICMODELS.OFFICES.COUNTRY IN ('DS_country')
After datasets are created we can make cascading report parameters CRP_country and CRP_office (keep in mind that UI doesn't let you to choose "Allow multiple values" on the upper levels, but we can change that in property editor after the parameters are made by going to advanced tab and changing "Scalar parameter type" property value to "Multi Value")
The only thing left is to pick lower level cascading parameters (CRP_office in our example) and go to script tab and add this on "beforeOpen":
// Do that if your selections are in String type.
var stringArray = params["CRP_country"].value.toString().split(",");
var result = "";
for(var i =0 ; i < stringArray.length ; i++){
if(i==0){
result = "'"+stringArray[i]+"'";
}
else{
result = result+",'"+stringArray[i]+"'";
}
}
// For String
this.queryText = this.queryText.replace("'DS_country'", result);
//For integer (the first part is useless)
//this.queryText = this.queryText.replace("'DS_country'",
params["CRP_country"].value);

BST delete - delete "tmp" causes lose of the tree

debug result
Attached my code for trying to delete a node in bst.
If I want to delete node 1, when specifying tmp = del in "if (del_node->l_ == NULL)", and remove tmp, then del is removed as well, and the tree data is lost. how can I solve this issue?
Example tree:
3
/ \
1 5
\
2
all data members and functions are declared public for simplicity.
void BST::DeleteNode(int data) {
BinaryTreeNode* &del_node = BST_Search(head_, data);
if (!del_node->l_ && !del_node->r_)
{
delete del_node;
del_node = nullptr;
return;
}
if (del_node->l_ == NULL)
{
BinaryTreeNode* tmp = del_node;
del_node = del_node->r_;
tmp = nullptr;
delete tmp;
return;
}
if (del_node->r_ == NULL)
{
BinaryTreeNode* tmp = del_node;
del_node = del_node->l_;
delete tmp;
return;
}
else
{
del_node->data_ = smallestRightSubTree(del_node->r_);
}
}
int BST::smallestRightSubTree(BinaryTreeNode* rightroot)
{
// if rightroot has no more left childs
if (rightroot && !rightroot->l_)
{
int tmpVal = rightroot->data_;
BinaryTreeNode* tmp = rightroot;
rightroot = rightroot->r_;
delete tmp;
return tmpVal;
}
return smallestRightSubTree(rightroot->l_);
}
int main()
{
BST bst;
bst.BST_Insert(bst.head_, 3);
bst.BST_Insert(bst.head_, 5);
bst.BST_Insert(bst.head_, 1);
bst.BST_Insert(bst.head_, 2);
bst.DeleteNode(1);
return 0;
}
Thanks for help!
EDIT: this is how tmp and del_node look like after the line "del_node = del_node->r_)" in the condition "if(del->l = null)"
void BST::BST_Insert(BinaryTreeNode*& head, int data) {
if (head == nullptr) {
head = new BinaryTreeNode(data, nullptr, nullptr);
return;
}
if (data > head->data_) {
BST_Insert(head->r_, data);
}
else {
BST_Insert(head->l_, data);
}
}
BinaryTreeNode* BST::BST_Search(BinaryTreeNode* root, int key) {
if (root == nullptr || root->data_ == key)
return root;
if (key > root->data_)
return BST_Search(root->r_, key);
return BST_Search(root->l_, key);
}
If your BST_Search returns a BinaryTreeNode* by value, what is the reference in BinaryTreeNode* &del_node = BST_Search(head_, data); actually referencing? It allocates a new temporary and references that. You probably wanted it to reference the variable that is holding the pointer in the tree so that you can modify the tree.
Your BST_Search would have to look like this:
BinaryTreeNode*& BST::BST_Search(BinaryTreeNode*& root, int key) {
if (root == nullptr || root->data_ == key)
return root;
if (key > root->data_)
return BST_Search(root->r_, key);
return BST_Search(root->l_, key);
}
I can't check whether this actually works, because you didn't provide a self-contained compilable example. But something along these lines.

Invalid Read of Size 4?

I'm running valgrind on a program, and while the program executes just fine, valgrind reports this:
==6542== Invalid read of size 4
==6542== at 0x8049C6F: Table::removeWebsite(Table&) (Table.cpp:146)
==6542== by 0x8049768: main (app.cpp:140)
==6542== Address 0x43f87d4 is 4 bytes inside a block of size 8 free'd
==6542== at 0x402B528: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-x86-linux.so)
==6542== by 0x8049BB0: Table::removeWebsite(Table&) (Table.cpp:124)
==6542== by 0x8049768: main (app.cpp:140)
I'm not entirely sure what is wrong. Here is the code that valgrind is pointing to...
bool Table::removeWebsite(Table& parm)
{
bool flag = false; //flag to show if an item is removed or not
int OriTableSize = currCapacity;
for (int index = 0; index < OriTableSize; index++) //search through array list, starting at index
{
Node *current = parm.aTable[index];
Node *prev = nullptr;
while (current != nullptr) //search through linked lists at array[index]
{
if (current->data->getRating() == 1) //search ratings for 1
{
if (prev == nullptr) //if current is the start of the list
{
if (current->next == nullptr) //if current is the only item in this list
{
delete current;
size--;
parm.aTable[index] = nullptr;
flag = true;
}
else
{
parm.aTable[index] = current->next; //point to the next item in list
delete current;
size--;
flag = true;
}
}
else //reset prev->next pointer to skip current
{
prev->next = current->next;
delete current;
size--;
flag = true;
}
}
prev = current;
current = current->next; //go to next position in linked list
}
}
if (flag == true)//at least one item was removed
return true;
else
return false;
}
That "delete current" points to a Node, which has:
struct Node
{
Node(const SavedWebsites& parm)
{
data = new SavedWebsites(parm);
next = nullptr;
};
~Node()
{
delete data;
next = nullptr;
}
SavedWebsites *data;
Node *next;
};
and the data in SavedWebsites has the destructor:
//Default Destructor
SavedWebsites::~SavedWebsites()
{
if (this->topic)
{
delete [] this->topic;
this->topic = nullptr;
}
if (this->website)
{
delete [] this->website;
this->website = nullptr;
}
if (this->summary)
{
delete [] this->summary;
this->summary = nullptr;
}
if (this->review)
{
delete [] this->review;
this->review = nullptr;
}
rating = 0;
}
*note the items "topic" "website" "summary" and "review" are all created with
... = new char[strlen(topic)+1] //(We have to use Cstrings)
I'm fairly new to all of this, so any ideas of what may be causing this valgrind invalid read?
You did not indicate which line corresponds to Table.cpp:146, but based on the Valgrind output, it looks like the allocation in question represents a Node instance because the size of 8 bytes matches (assuming a 32-bit system). The invalid read is triggered by the offset 4 of that instance and a size of 4, so this must correspond to the member next.
Table.cpp:146:
current = current->next; //go to next position in linked list
In case of a delete in the iteration, you access the deleted node current afterwards. You also initialize prev based on the invalid pointer, so the next pointer of the last valid node will not be updated correctly in case of deletes.
Your code seems to work fine (but is not) because its behavior depends on the allocator in use and other allocations. If the allocator were to fill the freed memory with a pattern or if that memory was reused immediately and written to, you'd see a segmentation fault.
To address this issue, I'd defer the delete. Before the next iteration, you can then either read the next node and delete the original current or update prev and read the next node.
bool del = false;
if (current->data->getRating() == 1) //search ratings for 1
{
if (prev == nullptr) //if current is the start of the list
{
if (current->next == nullptr) //if current is the only item in this list
{
parm.aTable[index] = nullptr;
}
else
{
parm.aTable[index] = current->next; //point to the next item in list
}
del = true;
flag = true;
}
else //reset prev->next pointer to skip current
{
prev->next = current->next;
del = true
flag = true;
}
}
if (del)
{
Node *deletenode = current;
current = current->next;
delete deletenode;
size--;
}
else
{
prev = current;
current = current->next; //go to next position in linked list
}

Deleting an node in BST

This is not an homework. I am just totally blocked on this. I know what to do but I am having difficulty manipulating the tree. please help.
I am trying to delete and node from an BST. I am able to lookup and find the parent and store it an tree.
package com.test.binarytree;
public class BinaryTreeDelete {
private Node root;
//create null binary tree
public BinaryTreeDelete(){
root = null;
}
//delete
public void delete(int target){
root = delete(root, target);
}
public Node delete(Node node, int target){
NodeWithParent temp = lookupFindParent(root, null, target);
if( node == null){
return null;
}
else{
if( node.left == null || node.right == null) //leaf node
{
//WHAT DO I DO HERE
//temp.parent.left = null;
//temp.parent.right = null;
//return null;
}
if( node.left != null && node.right == null ) //one child only on left
{
//WHAT DO I DO HERE
}
if( node.right != null && node.left == null ) //one child only on right
{
//WHAT DO I DO HERE
}
if( node.left != null && node.right != null ) //two children
{
//WHAT DO I DO HERE
}
}
return null;
}
private NodeWithParent lookupFindParent(Node node, Node parentNode, int target){
if( node == null ){
return null;
}
if( node.data == target){
return new NodeWithParent(node, parentNode);
}
else if( node.data > target ){
parentNode = node;
return lookupFindParent(node.left, parentNode, target);
}
else{
parentNode = node;
return lookupFindParent(node.right, parentNode, target);
}
}
//insert
public void insert(int data){
root = insert(root, data);
}
public Node insert (Node node, int data){
if(node == null){
node = new Node(data);
}
else{
if( data <= node.data ){
node.left = insert(node.left, data);
}
else{
node.right = insert(node.right, data);
}
}
return node;
}
//print tree
public void printTree(){
printTree(root);
System.out.println();
}
//print tree
private void printTree(Node node) {
if (node == null) return;
// left, node itself, right
printTree(node.left);
System.out.print(node.data + " ");
printTree(node.right);
}
//node class
public static class Node{
Node left;
Node right;
int data;
Node(int newNode){
data = newNode;
left = null;
right = null;
}
}
//node class
public static class NodeWithParent{
Node current;
Node parent;
NodeWithParent(Node current, Node parent){
this.current = current;
this.parent = parent;
}
}
public static void main(String[] args) {
BinaryTreeDelete bt = new BinaryTreeDelete();
//insert with inserts - tree increases on right if inserted in order
bt = new BinaryTreeDelete();
bt.insert(5);
bt.insert(3);
bt.insert(7);
bt.insert(1);
bt.insert(4);
bt.insert(6);
bt.insert(9);
bt.printTree();
//bt.delete(3);
//bt.delete(4);
//bt.delete(6);
bt.delete(9);
//bt.delete(5);
bt.printTree();
}
}
I'm going to provide you the logic (that means you have to write the code yourself) of how to delete a node in a BST.
There are three cases.
Node to be deleted has both left and right child as null: Delete the node and make the parent point to null.
Node to be deleted has either left or right child (but not both) as null: Delete the node but make sure that the parent points to the valid child of the to-be-deleted node.
Node to be deleted has nether left child nor right child as null: In this case, you have to find the next greater element of the to-be-deleted node. This next greater element is the least element of the right subtree of the to-be-deleted node. Since this is the least element, it has at least one of its child as null. So swap the values of the to-be-deleted node with the next greater node. After you swap, delete this next greater node using points 1 and 2 (whichever is fitting to the situation). Now, why the next greater node and not any node. Because if you replace a node with its next greater node, the BST remains a BST. Try it out in an example and it will be clear.

How to access Topic name from pdfs using poppler?

I am using poppler, and I want to access topic or headings of a particular page number using poppler, so please tell me how to do this using poppler.
Using the glib API. Don't know which API you want.
I'm pretty sure there is no topic/heading stored with a particular page.
You have to walk the index, if there is one.
Walk the index with backtracking. If you are lucky, each index node contains a PopplerActionGotoDest (check type!).
You can grab the title from the PopplerAction object (gchar *title) and get the page number from the included PopplerDest (int page_num).
page_num should be the first page of the section.
Assuming your PDF has an index containing PopplerActionGotoDest objects.
Then you simply walk it, checking for the page_num.
If page_num > searched_num, go back one step.
When you are at the correct parent, walk the childs. This should give you the best match.
I just made some code for it:
gchar* getTitle(PopplerIndexIter *iter, int num, PopplerIndexIter *last,PopplerDocument *doc)
{
int cur_num = 0;
int next;
PopplerAction * action;
PopplerDest * dest;
gchar * title = NULL;
PopplerIndexIter * last_tmp;
do
{
action = poppler_index_iter_get_action(iter);
if (action->type != POPPLER_ACTION_GOTO_DEST) {
printf("No GOTO_DEST!\n");
return NULL;
}
//get page number of current node
if (action->goto_dest.dest->type == POPPLER_DEST_NAMED) {
dest = poppler_document_find_dest (doc, action->goto_dest.dest->named_dest);
cur_num = dest->page_num;
poppler_dest_free(dest);
} else {
cur_num = action->goto_dest.dest->page_num;
}
//printf("cur_num: %d, %d\n",cur_num,num);
//free action, as we don't need it anymore
poppler_action_free(action);
//are there nodes following this one?
last_tmp = poppler_index_iter_copy(iter);
next = poppler_index_iter_next (iter);
//descend
if (!next || cur_num > num) {
if ((!next && cur_num < num) || cur_num == num) {
//descend current node
if (last) {
poppler_index_iter_free(last);
}
last = last_tmp;
}
//descend last node (backtracking)
if (last) {
/* Get the the action and do something with it */
PopplerIndexIter *child = poppler_index_iter_get_child (last);
gchar * tmp = NULL;
if (child) {
tmp = getTitle(child,num,last,doc);
poppler_index_iter_free (child);
} else {
action = poppler_index_iter_get_action(last);
if (action->type != POPPLER_ACTION_GOTO_DEST) {
tmp = NULL;
} else {
tmp = g_strdup (action->any.title);
}
poppler_action_free(action);
poppler_index_iter_free (last);
}
return tmp;
} else {
return NULL;
}
}
if (cur_num > num || (next && cur_num != 0)) {
// free last index_iter
if (last) {
poppler_index_iter_free(last);
}
last = last_tmp;
}
}
while (next);
return NULL;
}
getTitle gets called by:
for (i = 0; i < num_pages; i++) {
iter = poppler_index_iter_new (document);
title = getTitle(iter,i,NULL,document);
poppler_index_iter_free (iter);
if (title) {
printf("title of %d: %s\n",i, title);
g_free(title);
} else {
printf("%d: no title\n",i);
}
}