Near-Neighbor Searching in Ternary Search Tree - algorithm

How is the search for the nearest neighbors in the tree? Trying to find information, I get only some formulas without illustrative examples.
enter image description here
Example of a function:
void nearsearch(Tptr p, char *s, int d)
{ if (!p || d < 0) return;
if (d > 0 || *s < p->splitchar)
nearsearch(p->lokid, s, d);
if (p->splitchar == 0) {
if ((int) strlen(s) <= d)
srcharr[srchtop++] = (char *) p->eqkid;
} else
nearsearch(p->eqkid, *s ? s+1:s,
(*s == p->splitchar) ? d:d-1);
if (d > 0 || *s > p->splitchar)
nearsearch(p->hikid, s, d);
}

Related

Segmentation fault is on terminal. Its the code to convert string to binary tree

Node * create(Node * root, int I, int J, string str)
{
if (I == J) { root -> data =str[I]; root -> left=NULL; root -> right=NULL; }
int i = 0, j = 0, k = 0, l = 0;
//// to store the data of root
string val;
for (i = I; i < J; i++) {
if (str[i] == '(') break;
val.push_back(str[i]);
}
root -> data = stoi(val);
stack < char > st;
for (j = i; j < J; j++) {
if (str[j] == '(') st.push(str[j]);
else if (str[j] == ')') st.pop();
if (st.empty()) break;
}
for (l = j + 1; l < J; l++) {
if (str[l] == '(') st.push(str[l]);
else if (str[l] == ')') st.pop();
if (st.empty()) break;
}
k = j + 1;
if (j - i == 2) root -> left -> data = str[i + 1];
else
root -> left = create(root -> left, i + 1, j - 1, str);
if (l == k) root -> right=NULL;
else if (l - k == 2) root -> right -> data = str[k + 1];
else
root -> right = create(root -> right, k + 1, l - 1, str);
return root;
}
Node * treeFromString(string str){
Node * p = create(p, 0, str.size() - 1, str);
return p;
}
Here I have initialized variables i , j , k , l to track the left child and right child bracket in the string. I , J are the range of the node for a particular activation record of recursion.
I assume you parsed some expression, by your code I pre-implemented it.
I just implement build a tree for following expression:
expression: |<symbol>| <integer> '(' <expression> ')' '('<expression>')'
symbol : any C++ `char` single byte character.
integer : any C++ valid int type value.
#include <iostream>
#include <string>
#include <string_view> // C++17 std::string_view
#include <charconv> // C++17 std::from_chars.
#include <cassert>
//simulate Node class
struct Node
{
Node *left, *right;
int data;
};
//1. use string_view instead of triple I, J, std::string.
//2. First argument Node* root - needn't. It should be local variable.
Node * create(std::string_view str)
{
assert(!str.empty());
if (str.size() == 1)
{
Node* root = new Node; //-> YOU should allocate a memory for root.
root -> data =str[0];
root -> left=nullptr; // use nullptr instead of NULL for c++11 or later.
root -> right=nullptr;
return root; // exit needed!
}
Node* root = new Node;
root->left = nullptr;
root->right = nullptr;
root->data = 0;
//// to store the data of root
//2. THERE NEED take an integer until first '(' symbol.
{
std::size_t i = 0;
while (i < str.size() && str[i] != '(' )
++i;
// str[0 .. i) - interval is an integer.
int val = 0;
(void)std::from_chars(str.data(), str.data() + i, val); // FOR simplifity don't check validness of conversation.
str.remove_prefix(i);
root->data = val;
}
//3. SKIP balanced '(' and ')'
/*stack < char > st;
for (j = i; j < J; j++) {
if (str[j] == '(') st.push(str[j]);
else if (str[j] == ')') st.pop();
if (st.empty()) break;
}
* */
/** we can implement it another way */
assert(!str.empty() && str[0] == '(' );
std::string_view within_bracket;
{
int balanced_brackets = 0;
std::size_t i = 0;
while (i < str.size())
{
if (str[i] == '(') ++ balanced_brackets;
else if (str[i] == ')' ) --balanced_brackets;
i++;
if (balanced_brackets == 0)
break;
}
assert (i > 0 && str[ i - 1 ] == ')' );
// 0 1 2 3
// str[0..i) - is '(' ... ')' symbols.
within_bracket = std::string_view(str.data() + 1, i - 2);
str.remove_prefix(i);
}
/****4. THIS second balanced bracket check */
std::string_view second_within_bracket;
/*
for (l = j + 1; l < J; l++) {
if (str[l] == '(') st.push(str[l]);
else if (str[l] == ')') st.pop();
if (st.empty()) break;
}
k = j + 1;
*/
assert(!str.empty() && str[0] == '(' );
// ========== second balanced brackets check ==========
{
std::size_t i = 0;
int balanced_brackets = 0;
while (i < str.size())
{
if (str[i] == '(') ++ balanced_brackets;
else if (str[i] == ')' ) --balanced_brackets;
i++;
if (balanced_brackets == 0)
break;
}
// 0 1 2 3
// str[0..i) - is '(' ... ')' symbols.
second_within_bracket = std::string_view(str.data() + 1, i - 2);
str.remove_prefix(i);
}
//================================
/*
if (j - i == 2) root -> left -> data = str[i + 1];
else
root -> left = create(i + 1, j - 1, str);
if (l == k) root -> right=NULL;
else if (l - k == 2) root -> right -> data = str[k + 1];
else
root -> right = create(root -> right, k + 1, l - 1, str);
*/
root->left = create(within_bracket);
root->right = create(second_within_bracket);
return root;
}
Node * treeFromString(std::string_view str){
Node * p = create(str);
return p;
}
void printTree(Node* root, int level = 0)
{
if (root==nullptr) return;
for (int i= 0; i < level; ++i) std::cout << "--";
std::cout << " data = " << root->data << std::endl;
printTree(root->left, level + 1);
printTree(root->right, level + 1);
}
int main(){
std::string str = "12(8(7)(5))(9(3)(2(1)(8)))";
Node * expr = treeFromString(str);
printTree(expr);
}
godbold output:
Program returned: 0
data = 12
-- data = 8
---- data = 55
---- data = 53
-- data = 9
---- data = 51
---- data = 2
------ data = 49
------ data = 56
This answer is a bit different, it assumes you are loading a tree of integer values from a string, that could be loaded from a file. Next time you ask a question about code, could you please explain a little bit what the code does? Guessing does take some time and some effort.
I've reused the main() and PrintTree() functions from Khurshid Normuradov's answer. I hope he won't mind.
I took the liberty to add modern c++ coding techniques because this question is tagged c++17, so you're getting an example in c++17.
#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
struct Node {
std::unique_ptr<Node> left = nullptr;
std::unique_ptr<Node> right = nullptr;
int value = 0;
};
std::unique_ptr<Node> treeFromString(std::string_view str) {
std::cout << "treeFromString(\"" << str << "\")\n";
if (str.empty()) return {};
auto node = std::make_unique<Node>();
// extract an int
auto pos = str.find_first_not_of("0123456789");
auto val = str.substr(0, pos);
// optional: std::stoi() would throw anyway in this case
if (val.empty())
throw std::runtime_error("invalid value in expression");
node->value = std::stoi(std::string{val});
if (val.length() == str.length()) return node;
str = str.substr(val.length());
// Both left/right parsing are similar and use this
// common subroutine.
// expects parens delimited string as input.
// param str in: str string to parse from
// out: whatever's left to parse
// returns string content within parens, parens not included.
auto extract_parens_contents = [](std::string_view& str) {
// right here would be the perfect place to insert code to skip
// whitespace if you ever needed to do that.
// find parens extent
int parens = 0;
auto parens_end =
std::find_if(str.begin(), str.end(), [&parens](char c) {
parens += (c == '(') - (c == ')');
return (parens == 0);
});
if (parens_end == str.end())
throw std::runtime_error("unbalanced parens in expression");
// extract result
auto result = std::string_view(
str.begin() + 1, std::distance(str.begin() + 1, parens_end));
// remove spent bytes from input stream
str = std::string_view(
parens_end + 1,
str.length() - std::distance(str.begin(), parens_end + 1));
return result;
};
node->left = treeFromString(extract_parens_contents(str));
node->right = treeFromString(extract_parens_contents(str));
return node;
}
// special thanks to user Khurshid Normuradov, who originally wrote the two functions below.
// it would be difficult to writing something that would be any better for the
// intended purpose.
void printTree(Node* root, int level = 0) {
if (root == nullptr) return;
for (int i = 0; i < level; ++i) std::cout << "--";
std::cout << " data = " << root->value << std::endl;
printTree(root->left.get(), level + 1);
printTree(root->right.get(), level + 1);
}
int main() {
std::string str = "12(8(7)(5))(9(3)(2(1)(8)))";
auto expr = treeFromString(str);
printTree(expr.get());
}
You can play with the code here: https://godbolt.org/z/ch3zv5KTT

Segment tree with lazy propagation for multiple of 3

Abridged problem: You're given an array of n elements, initially they are all 0.
You will receive two types of query: 0 index1 index2, in this case you have to increase by one all elements in range index1 index2(included).
Second type: 1 index1 index2, in this case you have to print a number rapresenting how many elements between index1 and index2(included) are divisible by 3.
Of course, as n is very large(10^6) the good approach is to use segment tree to store intervals, and also to use lazy propagation to update the tree in log n.
But I actually really don't know how to apply lazy propagation here, because you have to keep into account three possible states for every number( may be 3k,3k+1,3k+2), and not just two as the flipping coins problem.
If I put a flag on some interval that is included in the interval of my query, I have to update it looking at the original array and at its value, but when I have to update the son of this interval I have to do the same again and this is a wasteful of time....
Any better idea? I search on the net but found nothing ...
EDIT: I follow your suggestions and I code this( C++), and works for some base cases, but when I submit it I get just 10/100 points, what is wrong with it ? (I know it's a bit long and there are no much comments but it's a simple Segment Tree with lazy propagation, if you don't understand something, please tell me!
NOTE: st[p].zero contains elements that are 0 mod 3 in interval stored in index p, st[p].one elements 1 mod 3, and st[p].two elements 2 mod 3; When I update I shift of one position these elements(0->1, 1->2, 2->0) and I use lazy. On updating, I return a pair < int , pair< int, int > >, just a simple way to store a triple of numbers, In this way a can return the difference of numbers 0,1,2 mod 3.
int sol;
struct mod{
mod(){ zero=0; one=0;two=0;}
int zero;
int one;
int two;
};
class SegmentTree {
public: int lazy[MAX_N];
mod st[MAX_N];
int n;
int left (int p) { return p << 1; }
int right(int p) { return (p << 1) + 1; }
void build(int p, int L, int R){
if(L == R)
st[p].zero=1;
else{
st[p].zero = R - L + 1;
build(left(p), L, (L + R) / 2);
build(right(p), ((L + R) / 2) + 1, R);
}
return;
}
void query(int p, int L, int R, int i, int j) {
if (L > R || i > R || j < L) return;
if(lazy[p]!=0){ // Check if this no has to be updated
for(int k=0;k<lazy[p];k++){
swap(st[p].zero,st[p].two);
swap(st[p].one, st[p].two);
}
if(L != R){
lazy[left(p)] = (lazy[left(p)] + lazy[p]) % 3;
lazy[right(p)] = (lazy[right(p)] + lazy[p]) % 3;
}
lazy[p] = 0;
}
if (L >= i && R <= j) { sol += st[p].zero; return; }
query(left(p) , L , (L+R) / 2, i, j);
query(right(p), (L+R) / 2 + 1, R , i, j);
return;
}
pair < int, ii > update_tree(int p, int L, int R, int i, int j) {
if (L > R || i > R || j < L){
pair< int, pair< int, int > > PP; PP.first=PP.second.first=PP.second.second=INF;
return PP;
}
if(lazy[p]!=0){ // Check if this no has to be updated
for(int k=0;k<lazy[p];k++){
swap(st[p].zero,st[p].two);
swap(st[p].one, st[p].two);
}
if(L != R){
lazy[left(p)] = (lazy[left(p)] + lazy[p]) % 3;
lazy[right(p)] = (lazy[right(p)] + lazy[p]) % 3;
}
lazy[p] = 0;
}
if(L>=i && R<=j){
swap(st[p].zero, st[p].two);
swap(st[p].one, st[p].two);
if(L != R){
lazy[left(p)] = (lazy[left(p)] + 1) % 3;
lazy[right(p)] = (lazy[right(p)] + 1) % 3;
}
pair< int, pair< int, int > > t; t.first = st[p].zero-st[p].one; t.second.first = st[p].one-st[p].two; t.second.second = st[p].two-st[p].zero;
return t;
}
pair< int, pair< int, int > > s = update_tree(left(p), L, (L+R)/2, i, j); // Updating left child
pair< int, pair< int, int > > s2 = update_tree(right(p), 1+(L+R)/2, R, i, j); // Updating right child
pair< int, pair< int, int > > d2;
d2.first = ( (s.first!=INF ? s.first : 0) + (s2.first!=INF ? s2.first : 0) ); // Calculating difference from the ones given by the children
d2.second.first = ( (s.second.first!=INF ? s.second.first : 0) + (s2.second.first!=INF ? s2.second.first : 0) );
d2.second.second = ( (s.second.second!=INF ? s.second.second : 0) + (s2.second.second!=INF ? s2.second.second : 0) );
st[p].zero += d2.first; st[p].one += d2.second.first; st[p].two += d2.second.second; // Updating root
return d2; // Return difference
}
public:
SegmentTree(const vi &_A) {
n = (int)_A.size();
build(1, 0, n - 1);
}
void query(int i, int j) { return query(1, 0, n - 1, i, j); }
pair< int, pair< int, int > > update_tree(int i, int j) {
return update_tree(1, 0, n - 1, i, j); }
};
int N,Q;
int main() {
FILE * in; FILE * out;
in = fopen("input.txt","r"); out = fopen("output.txt","w");
fscanf(in, "%d %d" , &N, &Q);
//cin>>N>>Q;
int arr[N];
vi A(arr,arr+N);
SegmentTree *st = new SegmentTree(A);
for(int i=0;i<Q;i++){
int t,q,q2;
fscanf(in, "%d %d %d " , &t, &q, &q2);
//cin>>t>>q>>q2;
if(q > q2) swap(q, q2);
if(t){
sol=0;
st->query(q,q2);
fprintf(out, "%d\n", sol);
//cout<<sol<<endl;
}
else{
pair<int, pair< int, int > > t = st->update_tree(q,q2);
}
}
fclose(in); fclose(out);
return 0;
}
You can store two values in each node:
1)int count[3] - how many there are 0, 1 and 2 in this node's segment.
2)int shift - shift value(initially zero).
The operations are performed in the following way(I use pseudo code):
add_one(node v)
v.shift += 1
v.shift %= 3
propagate(node v)
v.left_child.shift += v.shift
v.left_child.shift %= 3
v.right_child.shift += v.shift
v.right_child.shift %= 3
v.shift = 0
for i = 0..2:
v.count[i] = get_count(v.left, i) + get_count(v.right, i)
get_count(node v, int remainder)
return v.count[(remainder + v.shift) % 3]
The number of elements divisible by 3 for a node v is get_count(v, 0).
Update for a node is add_one operation. In general, it can be used as an ordinary segment tree(to answer range queries).
The entire tree update looks like that:
update(node v, int left, int right)
if v is fully covered by [left; right]
add_one(v)
else:
propagate(v)
if [left; right] intersects with the left child:
update(v.left, left, right)
if[left; right] intersects with the right child:
update(v.right, left, right)
for i = 0..2:
v.count[i] = get_count(v.left, i) + get_count(v.right, i)
Getting the number of elements divisible by 3 is done in similar manner.
It seems that you never have to care about the values of the elements, only their values modulo 3.
Keep a segment tree, using lazy updates as you suggest. Each node knows the number of things that are 0, 1, and 2 modulo 3 (memoization).
Each update hits log(n) nodes. When an update hits a node, you remember that you have to update the descendants (lazy update) and you cycle the memoized number of things in the subtree that are 0, 1, and 2 modulo 3.
Each query hits log(n) nodes; they're the same nodes an update of the same interval would hit. Whenever a query comes across a lazy update that hasn't been done, it pushes the update down to the descendants before recursing. Apart from that, all it does is it adds up the number of elements that are 0 modulo 3 in each maximal subtree completely contained in the query interval.

How to convert DFS algorithm using recursion to algorithm with normal iteration?

I have implemented successfully DFS (Deep First Search) Algorithm by using recursion but I dont know how to use normal iteration instead.
Below is my code with recursive calls.
data[1000][1000];
mark[1000][1000];// The array marks vertex visited
void dfs(int x, int y, int label){
if(x < 0 || x == SIZE)
return;
if(y < 0 || y == SIZE)
return;
if(data[x][y] == 0 || mark[x][y] != 0)
return;
mark[x][y] = label;
dfs(x + 1, y, label);
dfs(x, y + 1, label);
dfs(x - 1, y, label);
dfs(x, y - 1, label);
}
Please help me convert recursion to loops like for or while.
Thank you all in advance.
You can make a new structure and use stack. make_tuple(int x,int y,int label) returns tuple type.
typedef struct
{
int x,y,label;
} tuple;
stack<tuple > s;
s.push(make_tuple(initialx,initialy,initiallabel));
while(!s.empty())
{
tuple p = s.top();
s.pop();
int x = p.x;
int y = p.y;
int label = p.label;
if(x < 0 || x == SIZE)
continue;
if(y < 0 || y == SIZE)
continue;
if(data[x][y] == 0 || mark[x][y] != 0)
continue;
mark[x][y] = label;
s.push(make_tuple(x + 1, y, label));
s.push(make_tuple(x, y + 1, label));
s.push(make_tuple(x - 1, y, label));
s.push(make_tuple(x, y - 1, label));
}

Dynamic Programming Altogorithm

I'm trying to construct an algorithm that runs at O(nb) time with the following input/question:
input: an array A[1..n] of n different integers and an integer b (i am assuming that the numbers in A are sequential, starting at 1 ending at n, i.e. for n=4 A[1,2,3,4].
question: in how many ways can b be written as the sum of elements of the array when elements in A[] can only be used once?
I've kind of hit a wall on this one. I'm looking for some kind of recursive solution, but I don't see how to avoid using repeat numbers. Like, for instance, if we started at 1 and stored all the ways to make one (just 1) then 2 (just 2) then three (3 or 2+1) etc, it shouldn't be hard to see how many ways we can make larger numbers. But if, for instance, we take 5, we will see that it can be broken into 4+1, and 4 can be further broken down into 3+1, so then we would see 2 solutions (4+1, and 3+1+1), but one of those has a repeat of a number. Am I missing something obvious? Thanks so much!
Recursive and dynamic solutions in C:
#include <stddef.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uchar;
typedef unsigned int uint;
typedef struct tAddend
{
struct tAddend* pPrev;
uint Value;
} tAddend;
void findRecursiveSolution(uint n, uint maxAddend, tAddend* pPrevAddend)
{
uint i;
for (i = maxAddend; ; i--)
{
if (n == 0)
{
while (pPrevAddend != NULL)
{
printf("+%u", pPrevAddend->Value);
pPrevAddend = pPrevAddend->pPrev;
}
printf("\n");
return;
}
if (n >= i && i > 0)
{
tAddend a;
a.pPrev = pPrevAddend;
a.Value = i;
findRecursiveSolution(n - i, i - 1, &a);
}
if (i <= 1)
{
break;
}
}
}
void printDynamicSolution(uchar** pTable, uint n, uint idx, uint sum, tAddend* pPrevAddend)
{
uchar el = pTable[idx][sum];
assert((el != 0) && (el != 5) && (el != 7));
if (el & 2) // 2,3,6 - other(s)
{
printDynamicSolution(pTable,
n,
idx - 1,
sum,
pPrevAddend);
}
if (el & 4) // self + other(s)
{
tAddend a;
a.pPrev = pPrevAddend;
a.Value = idx + 1;
printDynamicSolution(pTable,
n,
idx - 1,
sum - (idx + 1),
&a);
}
if (el & 1) // self, found a solution
{
tAddend a;
a.pPrev = pPrevAddend;
a.Value = idx + 1;
pPrevAddend = &a;
while (pPrevAddend != NULL)
{
printf("+%u", pPrevAddend->Value);
pPrevAddend = pPrevAddend->pPrev;
}
printf("\n");
}
}
void findDynamicSolution(uint n)
{
uchar** table;
uint i, j;
if (n == 0)
{
return;
}
// Allocate the DP table
table = malloc(sizeof(uchar*) * n);
if (table == NULL)
{
printf("not enough memory\n");
return;
}
for (i = 0; i < n; i++)
{
table[i] = malloc(n + 1);
if (table[i] == NULL)
{
while (i > 0)
{
free(table[--i]);
}
free(table);
printf("not enough memory\n");
return;
}
}
// Fill in the DP table
for (i = 0; i < n; i++)
{
for (j = 0; j <= n; j++)
{
if (i == 0)
{
table[i][j] = (i + 1 == j); // self
}
else
{
table[i][j] = (i + 1 == j) + // self
2 * (table[i - 1][j] != 0) + // other(s)
4 * ((j >= i + 1) && (table[i - 1][j - (i + 1)] != 0)); // self + other(s)
}
}
}
printDynamicSolution(table, n, n - 1, n, NULL);
for (i = 0; i < n; i++)
{
free(table[i]);
}
free(table);
}
int main(int argc, char** argv)
{
uint n;
if (argc != 2 || sscanf(argv[1], "%u", &n) != 1)
{
n = 10;
}
printf("Recursive Solution:\n");
findRecursiveSolution(n, n, NULL);
printf("\nDynamic Solution:\n");
findDynamicSolution(n);
return 0;
}
Output:
for 10:
Recursive Solution:
+10
+1+9
+2+8
+3+7
+1+2+7
+4+6
+1+3+6
+1+4+5
+2+3+5
+1+2+3+4
Dynamic Solution:
+1+2+3+4
+2+3+5
+1+4+5
+1+3+6
+4+6
+1+2+7
+3+7
+2+8
+1+9
+10
See also on ideone.
Let F(x,i) be the number of ways elements of A[1:i] can be summed to get x.
F(x,i+1) = F(x-A[i+1],i) + F(x,i)
That is it!
This is not a dynamic programming solution though. Non-recursive.
Assumption that arr is sorted in your case like [i....j] where a[i] <= a[j]
That's easy enough
void summer(int[] arr, int n , int b)
{
int lowerbound = 0;
int upperbound = n-1;
while (lowerbound < upperbound)
{
if(arr[lowerbound]+arr[upperbound] == b)
{
// print arr[lowerbound] and arr[upperbound]
lowerbound++; upperbound--;
}
else if(arr[lowerbound]+arr[upperbound] < b)
lowerbound++;
else
upperbound--;
}
}
The above program is easily modifiable to a recursive you need to only change the function definition by passing lowerbound and upperbound.
Case for termination is still lowerbound < upperbound
Base case is if arr[lowerbound] +arr[upperbound] == b
Edited based on comments
You will need to use a modified version of integer knapsack problem. The values of [i,j] both need to be modified accordingly. You are having the problem because you are not most probably modifying your i carefully, Increase your i accordingly then their will not be repetition like the one you are having.

Question on HyperOperation

I am trying to solve the following recurence program.
http://en.wikipedia.org/wiki/Hyper_operator
Here is my code. I know it has mistakes, but I have done what I could.
public class hyper {
public static int Hyper(int a, int b, int n) {
int t=0;
if (n == 0)
return b+1;
if ((n == 1) && (b == 0))
return a;
if ((n == 2) && (b == 0))
return 0;
if ((n >= 3) && (b == 0))
return 1;
t = Hyper(a, b-1, n);
return Hyper(a, t, n-1);
}
public static void main(String[] args) {
int n=3;
int a=5;
int b=7;
System.out.println(Hyper(a, b, n));
}
}
This is a straightforward translation of the Wikipedia definition:
public static long hyper(long n, long a, long b) {
return
(n == 0) ? b + 1 :
(n == 1 && b == 0) ? a :
(n == 2 && b == 0) ? 0 :
(n >= 3 && b == 0) ? 1 :
hyper(n-1, a, hyper(n, a, b-1));
}
Sample output:
System.out.println(hyper(0,2,3)); // prints "4" increment
System.out.println(hyper(1,2,3)); // prints "5" addition
System.out.println(hyper(2,2,3)); // prints "6" multiplication
System.out.println(hyper(3,2,3)); // prints "8" exponentiation
System.out.println(hyper(4,2,3)); // prints "16" tetration
System.out.println(hyper(5,2,3)); // throws StackOverflowError; too deep

Resources