I have a method for getting the successor and predecessor nodes in a binary search tree, but I am having some problems locating the bug in my code. Say I add nodes with the following keys: "C", "B", and "K". If I print the contents of my binary search tree, I get the following output:
"C" "some data 1"
"B" "some data 2"
"K" "some data 3"
When I add "B" it obviously has no predecessor or successor, so I just set those to empty strings:
root = root->insert(root, key, data);
root->getNextAndPrev(root, prev, next, key);
string p;
string n;
if (!prev) {
pred = "";
}
else {
pred = prev->getKey();
}
if (!next) {
succ = "";
}
else {
succ = next->getKey();
}
return new Entry(data, succ, pred);
When I add "B" I get the output that "B"s successor is "C" and the predecessor is "" as expected. However, when I add "K" to the tree, I get the output that "K"s predecessor is "C" and the successor is also "C". I am not sure why I am getting this error since I check to see if there is no successor (nothing coming after "K") set it to an empty string.
My Node class handles the insert() and getNextAndPrev() methods, and here is how I've implemented them:
void Node::getNextAndPrev(Node* root, string key) {
if (!root) return;
if (root->key == key){
if (root->left != NULL){
Node* tempNode = root->left;
while (tempNode->right != NULL) {
tempNode = tempNode->right;
}
prev= tempNode;
}
if (root->right != NULL){
Node* tempNode = root->right;
while (tempNode->left != NULL) {
tempNode = tempNode->left;
}
next = tempNode;
}
}
if (root->key > key) {
next = root;
getNextAndPrev(root->left, key);
}
else {
prev = root;
getNextAndPrev(root->right, key);
}
}
Why is it that by adding some keys out of order causes my getNextAndPrev to retrieve incorrect values?
Perhaps it has something to do with how I am inserting entries in my main. I have a loop set up as follows:
string command = "";
Entry* entry = new Entry("","","");
string def = "";
while (true) {
cout << "Enter command: ";
getline(cin, command);
if (parseCommand(command, "ADD") == 0) {
string tempCmd = processCommand(command, 3);
string key = tempCmd.substr(0, tempCmd.length() - 4);
string data = tempCmd.substr(tempCmd.length() - 4);
trim(key);
trim(data);
def = data;
entry = dict->modify(key, data);
cout << "added: " << key << " with definition of : " << def << " to the dictionary " << endl;
}
modify() gets called like so inside my Dictionary class:
Entry * Dictionary::modify(string key, string data) {
Entry * entry = new Entry("","","");
if (root) entry = search(key);
//inserting something into the dictionary
if (data != "" && !this->root->doesContain(this->root, key)) {
root = root->insert(root, key, data);
return entry;
}
}
And finally, my search() method that gets called inside modify():
Entry * Dictionary::search(string key) {
if (key == "") {
return new Entry("", getSmallestKey(), getLargestKey());
}
if (!this->root->doesContain(root, key)) {
root->getNextAndPrev(root, key);
string prev;
string next;
if (root->getPrevNode() != NULL) {
prev = root->getPrevious();
cout << "Predecessor is " << prev << " root is: " << root->getKey() << endl;
}
else {
prev = "";
cout << "No Predecessor" << endl;
}
if (root->getNextNode() != NULL) {
next = root->getNext();
cout << "Successor is " << next << " root is: " << root->getKey() << endl;
}
else {
next = "";
cout << "No Successor" << endl;
}
if (next == prev) {
if (next < key) {
next = "";
}
if (prev > key) {
prev = "";
}
}
return new Entry("", next, prev);
}
To illustrate the problem in detail, here is the output from running the above:
Enter command: ADD "FOO" "D"
lookup stuff: root: prev: next: // gets logged out when I insert into dictionary
added: "FOO" with a definition of: "D" to the dictionary
Enter command: ADD "BIN" "C"
No Predecessor
Successor is "FOO" root is: "FOO"
lookup stuff: root: prev: next: "FOO"
added: "BIN" with a definition of: "C" to the dictionary
Enter command: ADD "QUUX" "D"
Predecessor is "FOO" root is: "FOO"
Successor is "FOO" root is: "FOO"
lookup stuff: root: prev: "FOO" next:
added: "QUUX" with a definition of: "D" to the dictionary
Enter command: ADD "BAZ" "N"
Predecessor is "FOO" root is: "FOO"
Successor is "BIN" root is: "FOO"
lookup stuff: root: prev: "FOO" next: "BIN"
added: "BAZ" with a definition of: "N" to the dictionary
I can't figure out why when adding BAZ to the dictionary, the predecessor and successor is now out of place:
Enter command: ADD "BAZ" "N"
Predecessor is "FOO" root is: "FOO"
Successor is "BIN" root is: "FOO"
I hope your Node constructor
new Node(key, d)
sets the left and right fields to NULL.
By successor and predecessor I think you mean inorder traversal successor and predecessor. Well your code seems absolutely fine to me
The only possibility is that I think you are using common variables prev and next to get the predecessor and successor. So try using different variables for different nodes.
After you are done getting successor and predecssor for the node B, define new variables:
Node *prevK,*nextK;
and call the function getNextAndPrev() with these variables.
Related
I'm working on a self imposed challenge which involves implementing a linked list and an append function for it, which is giving me issues seemingly related to variable scope.
The append function loops through each link element until it reads a NULL value and then changes the data value associated with that link to the function input. The test outputs within the function seem to show it is working as intended, but when performing the same test outside the function, even after it is called gives a different output.
template <class T>
struct atom{
T data;
atom<T>* link = NULL;
};
template <class T>
void append_LL(atom<T> first, T input_data){
atom<T>* current_node = &first;
atom<T>* next_node = current_node->link;
int i = 0;
while (i < 4 && next_node != NULL) {
current_node = next_node;
next_node = next_node->link;
i ++;
}
current_node->data = input_data;
current_node->link = (atom<T>*)malloc(sizeof(atom<T>));
cout << "leaving node as: " << current_node->data << endl; //outputs 5
cout << "input nodes data: " << first.data << endl; //outputs 5
}
int main() {
int dd = 5;
atom<int> linked_list;
linked_list.data = 999;
append_LL(linked_list, dd);
cout << linked_list.data << endl; //outputs 999
}
Because you are not sending the same atom. You see the program is making a copy of the linked_list in the main function and sending that copy to the function.
If you want to modify the same linked_list then change
void append_LL(atom<T> first, T input_data){
to
void append_LL(atom<T> &first, T input_data){
That way you are sending the really atom not a copy of it.
Following code works for sorting of the list (Peter,10) (John,32) (Mary,50) (Carol,31)
Ordered lists:
List 1: (Carol,31) (Carol,31) (John,32) (Mary,50)
however the peter is lost and carol is getting repeated, please help to suggest where Iam going wrong. WHat do I need to change in the loop to get this correct
LinkedList& LinkedList::order()
{
int swapped;
Node *temp;
Node *lptr = NULL;
temp=head;
// Checking for empty list
do
{
swapped = 0 ;
current = head;
while (current->get_next() != lptr)
{
if (current->get_data() > current->get_next()->get_data())
{
temp->set_Node(current->get_data());
current->set_Node(current->get_next()->get_data());
current->get_next()->set_Node(temp->get_data());
swapped = 1;
}
current = current->get_next();
}
lptr = current;
}
while (swapped);
return *this;
}
I am unable to get the std::map find to locate the correct row in the std::map. The key is a class pointer and I have created a struct (tdEcApplDataMapEq) to compare the class's binary arrays for a match.'
The problem is it doesn't work. I call FoEcApplData::operator== when the find starts. It says the first entry does not a match and then the find returns out pointing to the first item on the std::map list. There is no attempt by find to search the other map entries. Also the one match test failed (false), so why is find saying its a match?
This probably has something to do with the std::map declaration. std::map says the third argument is for std::less, but I am doing a == vs. <.
If I change it to do < the same this happens. It enters FoEcApplData::operator< which return a true on the first check and find search stops with the search pointing to the 1st entry in the list.
How do I get find() to use the custom struct for the search?
My example adds 10 rows to FdTEcApplDataMap. It copies the CDH_DISABLE_XACT182 class into hold for the search later. I then do the find() test using hold as the search key.
Inside entry1
Inside entry2
Inside entry3<== this is the one I am searching for
Inside entry4
Inside entry5
Inside entry6
Inside entry7
Inside entry8
Inside entry9
Inside entry10
Inside entry1
This is the find:
auto hazard = ExcludedCmdDict.find(&hold);
if(hazard != ExcludedCmdDict.end())
{
std::cout << "found it " << hazard->second << std::endl;
}
This is the compare function being used:
bool FoEcApplData::operator==( const FoEcApplData& FoEcApplDataObject) const {
if(myNumOfBytes <= FoEcApplDataObject.NumOfBytes())
{
const EcTOctet* temp;
temp = FoEcApplDataObject.Data() ;
for(EcTInt i = 0; i < myNumOfBytes ; i++)
{
if(myData[i] != temp[i])
{
return false ;
}
}
return true;
}
else // myNumOfBytes > FoEcApplDataObject.NumOfBytes()
{
const EcTOctet* temp;
temp = FoEcApplDataObject.Data() ;
for(EcTInt i = 0; i < FoEcApplDataObject.NumOfBytes(); i++)
{
if(myData[i] != temp[i])
{
return false ;
}
}
return true;
}
}
This is the declaration for the std::map.
/*
Custom less for find on the FdTEcApplDataMap.
Needed since we are using pointers.
Returns - true - match, false - no match
node - pointer to the item you are looking for
node2 - pointer to an item on the list
*/
struct tdEcApplDataMapEq {
bool operator()(FoEcApplData *const& node, FoEcApplData *const& node2) const
{
return *node == *node2;
}
};
typedef std::map< FoEcApplData *, std::string, tdEcApplDataMapEq> FdTEcApplDataMap;
std::map expects the compare function to work like std::less. You need to use something along the lines of:
struct tdEcApplDataMapEq {
bool operator()(FoEcApplData *const& node, FoEcApplData *const& node2) const
{
return (*node < *node2); // Implement operator<() function for FoEcApplData
}
};
While at it, change the name of the struct to reflect the fact that it is trying to compute "less than".
struct tdEcApplDataMapLess {
bool operator()(FoEcApplData *const& node, FoEcApplData *const& node2) const
{
return (*node < *node2); // Implement operator<() function for FoEcApplData
}
};
i would like to explain my problem by the following example.
assume the word: abc
a has variants: ä, à
b has no variants.
c has variants: ç
so the possible words are:
abc
äbc
àbc
abç
äbç
àbç
now i am looking for the algorithm that prints all word variantions for abritray words with arbitray lettervariants.
I would recommend you to solve this recursively. Here's some Java code for you to get started:
static Map<Character, char[]> variants = new HashMap<Character, char[]>() {{
put('a', new char[] {'ä', 'à'});
put('b', new char[] { });
put('c', new char[] { 'ç' });
}};
public static Set<String> variation(String str) {
Set<String> result = new HashSet<String>();
if (str.isEmpty()) {
result.add("");
return result;
}
char c = str.charAt(0);
for (String tailVariant : variation(str.substring(1))) {
result.add(c + tailVariant);
for (char variant : variants.get(c))
result.add(variant + tailVariant);
}
return result;
}
Test:
public static void main(String[] args) {
for (String str : variation("abc"))
System.out.println(str);
}
Output:
abc
àbç
äbc
àbc
äbç
abç
A quickly hacked solution in Python:
def word_variants(variants):
print_variants("", 1, variants);
def print_variants(word, i, variants):
if i > len(variants):
print word
else:
for variant in variants[i]:
print_variants(word + variant, i + 1, variants)
variants = dict()
variants[1] = ['a0', 'a1', 'a2']
variants[2] = ['b0']
variants[3] = ['c0', 'c1']
word_variants(variants)
Common part:
string[] letterEquiv = { "aäà", "b", "cç", "d", "eèé" };
// Here we make a dictionary where the key is the "base" letter and the value is an array of alternatives
var lookup = letterEquiv
.Select(p => p.ToCharArray())
.SelectMany(p => p, (p, q) => new { key = q, values = p }).ToDictionary(p => p.key, p => p.values);
A recursive variation written in C#.
List<string> resultsRecursive = new List<string>();
// I'm using an anonymous method that "closes" around resultsRecursive and lookup. You could make it a standard method that accepts as a parameter the two.
// Recursive anonymous methods must be declared in this way in C#. Nothing to see.
Action<string, int, char[]> recursive = null;
recursive = (str, ix, str2) =>
{
// In the first loop str2 is null, so we create the place where the string will be built.
if (str2 == null)
{
str2 = new char[str.Length];
}
// The possible variations for the current character
var equivs = lookup[str[ix]];
// For each variation
foreach (var eq in equivs)
{
// We save the current variation for the current character
str2[ix] = eq;
// If we haven't reached the end of the string
if (ix < str.Length - 1)
{
// We recurse, increasing the index
recursive(str, ix + 1, str2);
}
else
{
// We save the string
resultsRecursive.Add(new string(str2));
}
}
};
// We launch our function
recursive("abcdeabcde", 0, null);
// The results are in resultsRecursive
A non-recursive version
List<string> resultsNonRecursive = new List<string>();
// I'm using an anonymous method that "closes" around resultsNonRecursive and lookup. You could make it a standard method that accepts as a parameter the two.
Action<string> nonRecursive = (str) =>
{
// We will have two arrays, of the same length of the string. One will contain
// the possible variations for that letter, the other will contain the "current"
// "chosen" variation of that letter
char[][] equivs = new char[str.Length][];
int[] ixes = new int[str.Length];
for (int i = 0; i < ixes.Length; i++)
{
// We start with index -1 so that the first increase will bring it to 0
equivs[i] = lookup[str[i]];
ixes[i] = -1;
}
// The current "workin" index of the original string
int ix = 0;
// The place where the string will be built.
char[] str2 = new char[str.Length];
// The loop will break when we will have to increment the letter with index -1
while (ix >= 0)
{
// We select the next possible variation for the current character
ixes[ix]++;
// If we have exausted the possible variations of the current character
if (ixes[ix] == equivs[ix].Length)
{
// Reset the current character to -1
ixes[ix] = -1;
// And loop back to the previous character
ix--;
continue;
}
// We save the current variation for the current character
str2[ix] = equivs[ix][ixes[ix]];
// If we are setting the last character of the string, then the string
// is complete
if (ix == str.Length - 1)
{
// And we save it
resultsNonRecursive.Add(new string(str2));
}
else
{
// Otherwise we have to do everything for the next character
ix++;
}
}
};
// We launch our function
nonRecursive("abcdeabcde");
// The results are in resultsNonRecursive
Both heavily commented.
This question has been asked many times and I googled many places but still couldn't find one place where I can get step-by-step instruction for writing trie implementation. Please help me out
preferred language is Java or Python
Thank you
I have written a tries for string searching in java. Its pretty simple:
here are the steps:
Node class is like this:
public class Trienode {
char c;
Trienode parent;
ArrayList<Trienode> childs;
}
Trienode addString{ String str, Trienode root ){
if(str.length == 0) return root;
String newstr = [str without the first char];
char c = str[0];
Trienode newnode = root[c - '0'];
if(newnode == null){
newnode = new Trienode();
newnode.c = c;
newnode.parent = root;
}
return addString(newstr, newnode);
}
you can create search etc on the same line.
#!/usr/bin/env python
import sys
class Node:
def __init__(self):
self.next = {} #Initialize an empty hash (python dictionary)
self.word_marker = False
# There can be words, Hot and Hottest. When search is performed, usually state transition upto leaf node is peformed and characters are printed.
# Then in this case, only Hottest will be printed. Hot is intermediate state. Inorder to mark t as a state where word is to be print, a word_marker is used
def add_item(self, string):
''' Method to add a string the Trie data structure'''
if len(string) == 0:
self.word_marker = True
return
key = string[0] #Extract first character
string = string[1:] #Create a string by removing first character
# If the key character exists in the hash, call next pointing node's add_item() with remaining string as argument
if self.next.has_key(key):
self.next[key].add_item(string)
# Else create an empty node. Insert the key character to hash and point it to newly created node. Call add_item() in new node with remaining string.
else:
node = Node()
self.next[key] = node
node.add_item(string)
def dfs(self, sofar=None):
'''Perform Depth First Search Traversal'''
# When hash of the current node is empty, that means it is a leaf node.
# Hence print sofar (sofar is a string containing the path as character sequences through which state transition occured)
if self.next.keys() == []:
print "Match:",sofar
return
if self.word_marker == True:
print "Match:",sofar
# Recursively call dfs for all the nodes pointed by keys in the hash
for key in self.next.keys():
self.next[key].dfs(sofar+key)
def search(self, string, sofar=""):
'''Perform auto completion search and print the autocomplete results'''
# Make state transition based on the input characters.
# When the input characters becomes exhaused, perform dfs() so that the trie gets traversed upto leaves and print the state characters
if len(string) > 0:
key = string[0]
string = string[1:]
if self.next.has_key(key):
sofar = sofar + key
self.next[key].search(string,sofar)
else:
print "No match"
else:
if self.word_marker == True:
print "Match:",sofar
for key in self.next.keys():
self.next[key].dfs(sofar+key)
def fileparse(filename):
'''Parse the input dictionary file and build the trie data structure'''
fd = open(filename)
root = Node()
line = fd.readline().strip('\r\n') # Remove newline characters \r\n
while line !='':
root.add_item(line)
line = fd.readline().strip('\r\n')
return root
if __name__ == '__main__':
if len(sys.argv) != 2:
print "Usage: ", sys.argv[0], "dictionary_file.txt"
sys.exit(2)
root = fileparse(sys.argv[1])
print "Input:",
input=raw_input()
root.search(input)
I'm not a Java or Python coder, but can give you a very simple c# trie implementation. It's very very simple so I'm sure you could map it to Java.
Here it is:
public class Trie<T> : Dictionary<T, Trie<T>>
{
}
Done. Told you it was simple. But it is a trie and it works.
Here is implementation:-
import java.util.HashMap;
public class Tries {
class Node {
HashMap<Character, Node> children;
boolean end;
public Node(boolean b){
children = new HashMap<Character, Tries.Node>();
end = false;
}
}
private Node root;
public Tries(){
root = new Node(false);
}
public static void main(String args[]){
Tries tr = new Tries();
tr.add("dog");
tr.add("doggy");
System.out.println(tr.search("dogg"));;
}
private boolean search(String word) {
Node crawl = root;
int n = word.length();
for(int i=0;i<n;i++){
char ch = word.charAt(i);
if(crawl.children.get(ch) == null){
return false;
}
else {
crawl = crawl.children.get(ch);
if(i==n-1 && crawl.end == true){
return true;
}
}
}
return false;
}
private void add(String word) {
Node crawl = root;
int n = word.length();
for(int i=0;i<n;i++){
char ch = word.charAt(i);
if(crawl.children.containsKey(ch)){
crawl = crawl.children.get(ch);
}
else {
crawl.children.put(ch, new Node(false));
Node temp = crawl.children.get(ch);
if(i == n-1){
temp.end = true;
}
crawl = temp;
System.out.println(ch + " " + crawl.end);
}
}
}
}
Just use hashmap and keep track of end of word.