This is my first post on Stackoverflow. Please forgive me if my post format is not correct. I will try to learn as quick as possible. :)
So recently I am learning about BST. And I am practicing my skills on validating if a given Binary Tree is really a BST(duplicates are allowed as right child.) I tried recursion method and it works but the performance is not as good as I expected for a large given tree. So I tried to use Morris Algorithm to do the work. First I do an in-order traverse to see if the given tree is a BST. Then, I need to validate if all the duplicates are actually the right children of their parents. However, I am stuck on how to make that happen. So I am wondering if someone can give me some hints on that please? Or there's other ways to do that? Thank you very much.
The following are my currently code.
#include <algorithm>
#include <iostream>
#include <vector>
#include <limits.h>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
struct Node {
int key;
int left;
int right;
Node() : key(0), left(-1), right(-1) {}
Node(int key_, int left_, int right_) : key(key_), left(left_), right(right_) {}
};
bool IsBST(vector<Node> S) {
vector<size_t> result;
vector<size_t> check;
size_t cur_pos = 0;
size_t pre_pos = 0;
if (!S.size()) {
return true;
}
while (cur_pos != -1) {
size_t nxt_left_child = S[cur_pos].left;
if (nxt_left_child == -1) {
result.push_back(S[cur_pos].key);
check.push_back(cur_pos);
cur_pos = S[cur_pos].right;
}
else {
pre_pos = S[cur_pos].left;
while (S[pre_pos].right != -1 && S[pre_pos].right != cur_pos) {
pre_pos = S[pre_pos].right;
}
if (S[pre_pos].right == -1) {
S[pre_pos].right = cur_pos;
cur_pos = S[cur_pos].left;
}
else {
S[pre_pos].right = -1;
result.push_back(S[cur_pos].key);
check.push_back(cur_pos);
cur_pos = S[cur_pos].right;
}
}
}
if (std::is_sorted(result.begin(), result.end())) {
for (int i = 0; i < result.size() - 1; i++) {
if (result[i] == result[i + 1]) {
int temp = S[check[i]].right;
if (S[temp].key != S[check[i+1]].key) {
return false;
}
}
}
return true;
}
return false;
}
Related
I was learning to do a program online and found this solution and I wanted to execute and learn from it.
I am keep getting syntax error, can someone help with formatting it? I tried but couldn't understand the code that much to see where we need to provide indentation etc.,
I couldn't find a python example online for that question, I could only find c++ answer.
class Node {
public:
virtual int Compute() = 0;
inline void SetLeft(Node* left) {
left_ = left;
}
inline void SetRight(Node* right) {
right_ = right;
}
protected:
Node* left_ = nullptr;
Node* right_ = nullptr;
};
class SumNode : public Node {
public:
inline int Compute() override {
return left_->Compute() + right_->Compute();
}
};
class SubNode : public Node {
public:
inline int Compute() override {
return left_->Compute() - right_->Compute();
}
};
class MulNode : public Node {
public:
inline int Compute() override {
return left_->Compute() * right_->Compute();
}
};
class NumNode : public Node {
public:
NumNode(int num) : num_(num) {}
inline int Compute() override {
return num_;
}
private:
int num_;
};
class Solution {
public:
vector<int> diffWaysToCompute(string expression) {
vector<Node*> nodes;
// parse the expression
for(int i = 0; i < expression.size(); ++i) {
switch(expression[i]) {
case '+':
nodes.emplace_back(new SumNode());
break;
case '-':
nodes.emplace_back(new SubNode());
break;
case '*':
nodes.emplace_back(new MulNode());
break;
default:
int num = 0;
while(expression[i] >= '0' && expression[i] <= '9') {
num = num * 10 + expression[i] - '0';
++i;
}
--i;
nodes.emplace_back(new NumNode(num));
break;
}
}
vector<Node*> trees = GenerateAllTrees(nodes, 0, nodes.size() - 1);
for(Node* node : nodes) {
delete node;
}
vector<int> results;
for(Node* tree : trees) {
results.emplace_back(tree->Compute());
delete tree;
}
return results;
}
vector<Node*> GenerateAllTrees(const vector<Node*> nodes, int beg, int end) {
if(beg == end) {
return {new NumNode(nodes[beg]->Compute())};
}
vector<Node*> results;
for(int i = beg; i <= end; i++) {
// assuming the expression is well formed, operators will be in odd positions
if((i & 1) == 0) continue;
vector<Node*> left_trees = GenerateAllTrees(nodes, beg, i - 1);
vector<Node*> right_trees = GenerateAllTrees(nodes, i + 1, end);
for(Node* left : left_trees) {
for(Node* right : right_trees) {
nodes[i]->SetLeft(left);
nodes[i]->SetRight(right);
Node* result = new NumNode(nodes[i]->Compute());
results.emplace_back(result);
}
}
for(Node* t : left_trees) {
delete t;
}
for(Node* t : right_trees) {
delete t;
}
}
return results;
}
};
You just need to import the modules you are using, exactly like Python, except the syntax is different:
#include <vector>
#include <string>
using namespace std;
class Node {
public:
...
And because it is using emplace_back, if you are using g++, you'll need to specify -std=c++11 on the command line.
Also, you need to understand this is not a runnable example. These are just classes you could use in your own code. To run this, you'll need to supply a main() function. Maybe:
#include <iostream>
int main()
{
Solution s;
vector<int> result = s.diffWaysToCompute( "3+9*7-16" );
for( auto i : result )
cout << i << "\n";
}
Another day another seg fault I don't understand, I'm trying to implement tries for the first time and it is proving to be quite some challenge, I think it would be very helpful if someone could tell me what I'm doing wrong, would probably help me understand OOP better too I suppose, because I think the error is related to that.
The fault happens while searching and I wasn't able to understand it using the debugger myself.
Here is the code:
#include <vector>
#include <iostream>
using std::string, std::cout, std::vector;
class TrieNode {
private:
bool isLeaf;
vector<TrieNode*> ar = vector<TrieNode*>(26);
public:
TrieNode() {
isLeaf = false;
for(int i = 0; i < 26; i++) ar[i] = nullptr;
}
void insert(TrieNode *root, string key) {
TrieNode *crawl = root;
for(int i = 0; i < key.size(); i++) {
if(!crawl->ar[key[i]]) {
crawl->ar[key[i]] = new TrieNode();
}
crawl = crawl->ar[key[i]];
}
crawl->isLeaf = true;
}
bool search(TrieNode *root, string key) {
TrieNode *crawl = root;
for(int i = 0; i < key.size(); i++) {
if(!crawl->ar[key[i]]) {
return false;
}
crawl = crawl->ar[key[i]];
}
return crawl->isLeaf;
}
};
int main() {
TrieNode* head = new TrieNode();
head->insert(head, "hello");
cout << head->search(head, "hello");
}
Make your ar[key[i]] to something like ar[key[i]-'a'] if your string is say always lower-case.
Basically, key[i] is a char in the range of ['a'-'z']. When it's implicitly converted to an int, it's not in the range of [0,25], but rather equal to their ascii values.
I'm attempting to make some sort of autocomplete feature in c++. First by using a Trie and once that works (and most importantly, I know HOW it all works) I'll try it using a Ternary tree. But as for now I get a segmentation fault when ever I add words starting with a different characte than those already in the Trie.
Eg. we add "abc", "abcd" and "abcde" this is no problem. Later when I want to add (while the "abc" etc are still in the Trie) "xfce", "xfced" a segmentation fault occurs.
I've been debugging this for some while now and can't seem to find the problem.
I think the problem resides somewhere in Trie.cpp so that's the file I'll provide here. However it might be in the main function aswell but I don't wanna get yelled at for posting to much code...
#include "Trie.h"
#include <iostream>
Trie::Trie()
{
this->root = new Node(false);
}
Trie::~Trie()
{
}
Trie::Node::Node(bool isLeaf)
{
this->isLeaf = isLeaf;
}
void Trie::insert(const std::string& word)
{
Node* crawler = this->root;
int index;
for(int i = 0; i < word.length(); ++i)
{
index = CHAR_TO_INDEX(word.at(i));
if(!crawler->children[index])
{
crawler->children[index] = new Node(false);
}
crawler = crawler->children[index];
}
crawler->isLeaf = true;
}
int Trie::contains(const std::string& word)
{
int index;
Node* crawler = this->root;
for(int i = 0; i < word.length(); ++i)
{
index = CHAR_TO_INDEX(word.at(i));
if(!crawler->children[index])
{
return -1;
}
crawler = crawler->children[index];
}
return (crawler != NULL && crawler->isLeaf);
}
std::vector<std::string> Trie::possibleSuffixes(std::string& prefix)
{
Node* crawler = this->root;
int index;
std::vector<std::string> result;
for(int i = 0; i < prefix.length(); ++i)
{
index = CHAR_TO_INDEX(prefix.at(i));
crawler = crawler->children[index];
}
traverse(prefix, crawler, result);
return result;
}
void Trie::traverse(std::string prefix, Node* node, std::vector<std::string>& v)
{
if(node->isLeaf)
{
v.push_back(prefix);
}
for(int i = 0; i < ALPHABET; ++i)
{
if(node->children[i])
{
traverse(prefix + (char)('a' + i), node->children[i], v);
}
}
}
Entire Trie class:
#ifndef TRIE_H
#define TRIE_H
#include <string>
#include <vector>
#define ARRAYSIZE(a) sizeof(a / sizeof(a[0]))
#define ALPHABET 26
#define CHAR_TO_INDEX(c) ((int)c - (int)'a')
class Trie
{
private:
struct Node
{
Node(bool isLeaf);
struct Node *children[ALPHABET];
bool isLeaf;
};
Node *root;
void traverse(std::string prefix, Node* node, std::vector<std::string>& v);
public:
Trie();
~Trie();
int contains(const std::string& word); //Checks the existance of a specific word in the trie
void insert(const std::string& word); //Inserts new word in the trie if not already there
std::vector<std::string> possibleSuffixes(std::string& prefix);
};
Though you didn't mention about your Node class, I am assuming this -
class Node {
public:
bool isLeaf;
// must be >= 25 as you're inserting lowercase letters
// assuming your CHAR_TO_INDEX(ch) returns 0 based index
// e.g. 'a' => 0, 'b' => 1 ... 'z' => 25
Node* children[30];
// default constructor should be like this
Node(): isLeaf(false) {
for(int i = 0; i < 26; i++) {
children[i] = NULL;
}
}
~Node() {
for(int i = 0; i < 26; i++) {
if(children[i]) {
delete children[i];
children[i] = NULL;
}
}
delete this;
}
};
Please compare your Node class/struct whether its something like this.
I had a project to do in C++ (moreover, I had to use some stuff from C++11, specifically: custom iterators, smart pointers and chrono) which constructs suffix tree for specific string. When it comes down to constructing a tree, I think I did a good job - I have a proper tree, construction times and search times are looking rather good and there's not a single problem with this. However, I know I messed up with my TNode struct - I didn't use weak_ptrs, therefore in my tree class I had to build up hugeass destructor walking on every node and forcibly erasing any connections.
Anyway, I used Deleaker to check for possible memory leaks. There were none for "abracadabra" word. Unfortunately, it found some leaks for "lorem ipsum (...)". Most of them are linked with creating new nodes and I fail to understand where my problem is. I simply don't get it - it appears that every node is destructed when program is ending. Where did I make mistake?
Node.h:
#pragma once
#include <algorithm>
#include <vector>
#include <memory>
#include <Windows.h>
#define INF 1<<30
struct TNode : public std::enable_shared_from_this<TNode>{
long int indexStart;
long int indexEnd;
std::vector<std::shared_ptr<TNode>> children;
std::shared_ptr<TNode> suffixLink;
int count;
TNode(long int pIndexStart, int pCount) {
indexStart = pIndexStart;
indexEnd = INF;
children.clear();
suffixLink = nullptr;
count = pCount;
}
~TNode() {
//OutputDebugString(L"node dies\n");
}
int EdgeLength(long int pos) {
return min(indexEnd, pos+1) - indexStart;
}
};
tree.h
#pragma once
#include <memory>
#include <vector>
#include "IChildIterator.h"
#include "Node.h"
class CTree
{
public:
CTree();
~CTree();
void LoadString(std::string* newString);
void CreateTree();
bool FindPhrase(std::string* toFind);
void PrintSuffix(std::vector<long> indexes);
std::shared_ptr<TNode> GetRoot();
private:
std::shared_ptr<TNode> root;
std::shared_ptr<TNode> activeNode;
long int activeEdge;
long int activeLength;
std::string* string;
std::shared_ptr<TNode> lastAddedNode;
long int position;
long int remainder;
int count;
void AddSuffixLink(std::shared_ptr<TNode> node);
bool WalkDown(std::shared_ptr<TNode> node);
void ExtendTree();
char GetActiveEdge();
};
tree.cpp
#include "stdafx.h"
#include "Tree.h"
CTree::CTree()
{
std::shared_ptr<TNode> nowy(new TNode(-1, -1));
root = activeNode = nowy;
activeEdge = activeLength = 0;
lastAddedNode = nowy;
position = -1;
remainder = 0;
count = 0;
string = nullptr;
}
CTree::~CTree()
{
if (string) {
delete string;
}
std::vector<IChildIterator> iterstack;
iterstack.resize(0);
IChildIterator child(root, true);
while (true) {
if (0 == (*child)->children.size()) {
if (iterstack.size() == 0)
break;
child = iterstack.back();
iterstack.pop_back();
(*child)->children.erase((*child)->children.begin());
child++;
continue;
}
if ((*child)->children.front()->indexEnd != INF) {
iterstack.push_back(child);
child = IChildIterator(*child);
continue;
}
std::shared_ptr<TNode> temp = (*child)->children.front();
if (temp->suffixLink) temp->suffixLink = nullptr;
(*child)->children.erase((*child)->children.begin());
}
OutputDebugString(L"tree dies\n");
}
void CTree::LoadString(std::string* newString)
{
string = new std::string(*newString);
}
void CTree::CreateTree()
{
for (int i = 0; i < string->size(); i++) {
ExtendTree();
}
}
std::shared_ptr<TNode> CTree::GetRoot()
{
return root;
}
void CTree::AddSuffixLink(std::shared_ptr<TNode> node)
{
if (lastAddedNode) lastAddedNode->suffixLink = node;
lastAddedNode = node->shared_from_this();
}
bool CTree::WalkDown(std::shared_ptr<TNode> node)
{
if (activeLength >= node->EdgeLength(position)) {
activeEdge += node->EdgeLength(position);
activeLength -= node->EdgeLength(position);
activeNode = node;
return true;
}
return false;
}
void CTree::ExtendTree()
{
++position;
lastAddedNode = nullptr;
remainder++;
while (remainder > 0) {
if (activeLength == 0) activeEdge = position;
std::shared_ptr<TNode> selected = nullptr;
for each (std::shared_ptr<TNode> child in activeNode->children) {
if (string->at(child->indexStart) == GetActiveEdge()) {
selected = child;
break;
}
}
if (!selected) {
std::shared_ptr<TNode> newLeaf(new TNode(position, count++));
activeNode->children.push_back(newLeaf);
AddSuffixLink(activeNode);
}
else {
if (WalkDown(selected)) continue;
if (string->at(selected->indexStart + activeLength) == string->at(position)) {
activeLength++;
AddSuffixLink(activeNode);
break;
}
//split
if (selected->children.size() > 0) {
long lastStart = selected->indexStart;
selected->indexStart = selected->indexStart + activeLength;
std::shared_ptr<TNode> newNode(new TNode(lastStart, count++));
newNode->indexEnd = selected->indexStart;
newNode->children.push_back(selected);
std::shared_ptr<TNode> yetAnotherNewLeaf(new TNode(position, count++));
newNode->children.push_back(yetAnotherNewLeaf);
std::vector<std::shared_ptr<TNode>>::iterator iter;
iter = activeNode->children.begin();
while (true) {
if (*iter == selected) {
activeNode->children.insert(iter, newNode);
iter = activeNode->children.begin();
while (true) {
if (*iter == selected) {
activeNode->children.erase(iter);
break;
}
iter++;
}
break;
}
iter++;
}
AddSuffixLink(newNode);
}
else {
selected->indexEnd = selected->indexStart + activeLength;
std::shared_ptr<TNode> newLeaf(new TNode(selected->indexEnd, count++));
selected->children.push_back(newLeaf);
std::shared_ptr<TNode> yetAnotherNewLeaf(new TNode(position, count++));
selected->children.push_back(yetAnotherNewLeaf);
AddSuffixLink(selected);
}
}
remainder--;
if (activeNode == root && activeLength > 0) {
activeLength--;
activeEdge = position - remainder + 1;
}
else {
if (activeNode->suffixLink) {
activeNode = activeNode->suffixLink;
}
else {
activeNode = root;
}
}
}
}
char CTree::GetActiveEdge()
{
return string->at(activeEdge);
}
Memory leaks:
during creation of every new node in ExtendTree() method
tree constructor
on line
iter = activeNode->children.begin();
I'd be grateful for any kind of tip how to fix this.
There's a potential leak when calling LoadString:
void CTree::LoadString(std::string* newString)
{
string = new std::string(*newString);
}
This function does not delete previously allocated string.
Your method for creating shared_ptr objects is also odd. This shouldn't necessarily cause memory leaks but it's very strange to behold. You are, for example, doing this:
std::shared_ptr<TNode> newLeaf(new TNode(position, count++));
When you should be doing this:
std::shared_ptr<TNode> newLeaf = std::make_shared<TNode>(position, count++)
Below is my implementation to keep track of the size of each tree in the disjoint set forest.
Can you please tell me what is wrong with it ? I am trying to solve UVa problem https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3638
#include <iostream>
#include <cstdio>
#include <unordered_map>
using namespace std;
class Node {
public :
int id;
Node *parent;
unsigned long long rank;
Node(int id) {
this->id = id;
// this->data = data;
this->rank =1; //size here
this->parent = this;
}
friend class DisjointSet;
};
class DisjointSet {
unordered_map<int,Node*> nodesMap;
Node *find_set_helper(Node *aNode) {
if (aNode == aNode->parent) {
return aNode->parent;
}
return find_set_helper(aNode->parent);
}
void link(Node *xNode,Node *yNode) {
if( xNode->rank > yNode->rank) {
yNode->parent = xNode;
xNode->rank += yNode->rank;
}
// else if(xNode-> rank < yNode->rank){
// xNode->parent = yNode;
// yNode->rank += xNode->rank;
// }
else {
xNode->parent = yNode;
yNode->rank += xNode->rank;
}
}
public:
DisjointSet() {
}
void AddElements(int sz) {
for(int i=0;i<sz;i++)
this->make_set(i);
}
void make_set(int id) {
Node *aNode = new Node(id);
this->nodesMap.insert(make_pair(id,aNode));
}
void Union(int xId, int yId) {
Node *xNode = find_set(xId);
Node *yNode = find_set(yId);
if(xNode && yNode)
link(xNode,yNode);
}
Node* find_set(int id) {
unordered_map<int,Node*> :: iterator itr = this->nodesMap.find(id);
if(itr == this->nodesMap.end())
return NULL;
return this->find_set_helper(itr->second);
}
~DisjointSet(){
unordered_map<int,Node*>::iterator itr;
for(itr = nodesMap.begin(); itr != nodesMap.end(); itr++) {
delete (itr->second);
}
}
};
int main() {
int n,m,k,first,cur;
//freopen("in.in","r",stdin);
scanf("%d %d",&n,&m);
while(n != 0 || m != 0) {
DisjointSet *ds = new DisjointSet();
ds->AddElements(n); // 0 to n-1
//printf("\n n = %d m = %d",n,m);
for(int i=1;i<=m;i++) {
scanf("%d",&k);
//printf("\nk=%d",k);
if ( k > 0 ) {
scanf("%d",&first);
for(int j=2;j<=k;j++) {
scanf("%d",&cur);
ds->Union(first,cur);
}
}
}
Node *zeroSet = ds->find_set(0);
// unsigned long long count = ds->getCount(zeroSet->id);
printf("%llu\n",zeroSet->rank);
delete ds;
scanf("%d %d",&n,&m);
}
return 0;
}
The link function in the above code does the job of updating the tree size.
The solution to the problem is to find the set which elements 0 belongs to and get the size of the representative element of the set.
But I am getting wrong answer with this code.
Can you please help me
In your Union function, check if both nodes are already in the same set.
if(xNode && yNode && xNode != yNode)
link(xNode,yNode);