I use inorder to show result of search name which store in binary search tree but when i run it example i have: Employee name "abc" and "ab" and i input name ="abc" it show 2 of them.Anyone can help me what is my fault :( ty
public void searchFull(String name) {
EmployeeSLLNode p = root;
n=0;
if (p != null) {
inorder(p.left);
if(p.info.getFullname().equals(name)) {
n++;
System.out.printf("%2s %-5s %-8s %-6s %-6s%n", n, p.info.getID(), p.info.getFullname(), p.info.getAge(), p.info.getGender());
}
inorder(p.right);
}
}
In-order traversal is equivalent to iterating a TreeMap's entrySet.
final Map<String, Employee> employees = new TreeMap<String, Employee>();
...
for (final Map.Entry<String, Employee> entry : employees.entrySet()) {
/* iterating in-order */
}
TreeMap simply uses a binary search tree (in particular, according to the specification, a red-black tree). Consider using it instead of rolling your own solution ;-)
That being said, if you're intent on rolling your own, maybe try something like this...
public EmployeeSSLnode search(final EmployeeSSLnode root, final String name) {
EmployeeSSLnode left;
return root == null
? null
: (left = search(root.left, name)) == null
? root.info.getFullname().equals(name)
? root
: search(root.right, name)
: left;
}
I think this is what you can do.But ensure that your your tree doesn't have the duplicate names.
public void searchFull(EmployeeSLLnode p, String name) {
if (p == null)
return;
searchFull(p -> left, name);
if (p.info.getFullname().equals(name)) {
//This is the node do other stuff here
return;
}
searchFull(p -> right, name);
}
Also it would be better to do general search in BST instead of searching through Inorder. Inorder searcing in BST would actually ruin the whole purpose of BST. Compare the input Name with node using compareTo() method of String class and depending on whether name is alphabetically later or earlier move either to right or left.
Most of this code should be inside the inorder() method. Undoubtedly it actually is, so you have two prints, so you get two outputs. All the searchFull() method should do is call inorder(root).
Related
class ParentItem {
String itemName; //I want to get this property for all the objects in hierarchy
Integer itemCode;
List<ParentItem> childItem;
}
I want to get the names of the All Items(ParentItem name, ChildItem name, GrandChildItemName) using streams, how to achieve this? Assume the ChildItem also has a Child which means the ParentItem has a GrandChild! So there are 3 levels of Nesting. How to achieve this?
Try the following approach to recursively flatmap the child streams:
Stream<ParentItem> flatMapChildren(ParentItem item ) {
return Stream.concat( //flatMap replaces the item in the stream so we need concat() to keep it
Stream.of(item), //create a 1-element stream for the item that gets replaced
item.childItem.stream() //create a stream for the children
.flatMap(YourClass::flatMapChildren) //recursively add their children
);
}
Then use that on your top level stream:
List<ParentItem> topLevel = ....;
Stream<String> streamOfAllNames =
topLevel.flatMap(YourClass::flatMapChildren)
.map(ParentItem::getName);
Note: the implementation doesn't contain null checks etc. for simplicity reasons. Add those in your actual code.
public static void main(String[] args) {
ParentItem grandpa = new ParentItem();
List<String> listOfItemNames = Stream.of(grandpa)
.flatMap(Main::loadChildRecursively)
.map(ParentItem::getItemName)
.collect(Collectors.toList());
listOfItemNames.forEach(System.out::println);
}
private static Stream<ParentItem> loadChildRecursively(ParentItem parent) {
if (parent.getChildItem() != null && parent.getChildItem().size() > 0) {
return Stream.concat(parent.getChildItem().stream().flatMap(Main::loadChildRecursively), Stream.of(parent));
} else {
return Stream.of(parent);
}
}
An important thing to keep in mind is, when calling the recursive function always add / include your parent object, otherwise you'll end up only having the lowest level of children and no parents.
I made a Word Counter binary search tree that increments the count of a word when it is entered more than once. Both the word and word count are saved in the tree. I am attempting to print the highest count words first, and go down in descending count order.
I converted the BST to an ArrayList in order to do this, but now I cannot seem to figure out how to sort the list by decreasing count order. Here's what I have so far:
public ArrayList<String> toArray() {
ArrayList<String> result = new ArrayList<String>();
toArrayHelp(root, result);
Collections.sort(result);
return result;
}
private void toArrayHelp(Node<String, Integer> node, ArrayList<String> result) {
if (node == null) {
return;
}
toArrayHelp(node.left, result);
result.add("count: " + String.valueOf(node.count) + "/t word: " + node.data);
toArrayHelp(node.right, result);
}
I have tried Collections.sort() but that isn't ordering it by string, only by word.
traverse the tree, generating a List<Node<String, Integer>> from all elements
sort the List, ordering by the int part of the nodes
create a list retaining only the strings, in the same order
You are constructing the output string too soon: you need to sort the list first by using the count as a key, and afterwards print the results. You can make a simple wrapper that will contain the result:
public class WordCount implements Comparable<WordCount>{
private String word;
private Integer count;
//constructors, getters, setters etc..
#Override
public int compareTo(WordCount other) {
return Integer.compare(this.count, other.count);
}
}
and construct a List<WordCount> list while you traverse the tree. After you are done you just need to sort the list by Collections.sort(list) and print the results.
1.For DESC order use Collections.sort(result, Collections.reverseOrder()); because default sorting order is ASC.
2.Make sure that count's string representation has the same length. Otherwise, lexicographical order assumes 11 < 2:
List<String> list = Arrays.asList("11", "1", "2");
Collections.sort(list, Collections.reverseOrder());
System.out.println(list); // output: [2, 11, 1]
But if numbers have the same length works fine:
List<String> list = Arrays.asList("11", "01", "02");
Collections.sort(list, Collections.reverseOrder());
System.out.println(list); // output: [11, 02, 01]
How to add leading zeroes you can find here https://stackoverflow.com/a/275715/4671833.
Should be something like this result.add("count: " + String.format("%02d", String.valueOf(node.count)) + "/t word: " + node.data);
Two brief points: Let name selection and formatting be your friends! You'll want to make a habit of choosing simple and expressive variable names, and of keeping your code neatly formatted.
Let's start by putting this into clear steps:
(1) There is a source of word data, expressed as a tree of nodes. Avoiding too much detail, lets set the important details of the node type, and have the node tree available using a getter.
An important detail to mention is that the nodes are intended to be kept in a sorted binary tree that has distinct key values, and for which the value of any left node is strictly less than the value of the node, and the value of any right node is strictly greater than the value of the node. That has an important consequence which is that the values of the left sub-tree of a node are all strictly less than the value of the node, and the values of the right sub-tree are similarly all strictly greater than the value of the node.
public class Node<K, V> {
public K key;
public V value;
public Node<K, V> left;
public Node<K, V> right;
public Node(K key, V value) {
this.key = key;
this.value = value;
}
}
public Node<String, Integer> getRootNode() {
// Undetailed ...
}
(2) There are three main operations which are needed: An operation to collect the nodes of the tree into a list, an operation to sort this list, and an operation to display the sorted list:
public List<Node<String, Integer>> flatten(Node<String, Integer> rootNode) {
// Undetailed ...
}
public void sort(List<Node<String, Integer>> nodes) {
// Undetailed ...
}
public void print(List<Node<String, Integer>> nodes) {
// Undetailed ...
}
(3) This fits together, for example, as follows:
public void tester() {
Node<String, Integer> rootNode = getRootNode();
List<Node<String, Integer>> flatNodes = flatten(rootNode);
sort(flatNodes);
print(flatNodes)l
}
(4) What remains are to detail the several methods. We begin with 'flatten'. That will be implemented as a recursive operation. And, since passing around the storage for the flat list is simpler, the method will be split into two parts, one which allocates storage, and another which does the recursive processing. This technique of passing along a storage collection is typical of this sort of processing.
'flatten' makes use of the ordering property of a node with respect to the node's left node and the node's right node: 'flatten' adds all values of the left sub-tree to the flat nodes list, followed by the node, followed by all values of the right sub-tree.
public List<Node<String, Integer>> flatten(Node<String, Integer> rootNode) {
List<Node<String, Integer>> flatNodes = new ArrayList<Node<String, Integer>>();
flatten(rootNode, flatNodes);
return flatNodes;
}
public void flatten(Node<String, Integer> node, List<Node<String, Integer>> flatNodes) {
if ( node == null ) {
return;
}
flatten(node.left, flatNodes);
flatNodes.add(node);
flatten(node.right, flatNodes);
}
(5) At a cost of clarity, this can be made somewhat more efficient by moving the null checks. For a fully balanced tree, this will avoid about 2/3's of the recursive calls, which is pretty good reduction. This only matters if the number of nodes is high. And a good compiler will likely convert the code in this fashion anyways.
public List<Node<String, Integer>> flatten(Node<String, Integer> rootNode) {
List<Node<String, Integer>> flatNodes = new ArrayList<Node<String, Integer>>();
if ( rootNode != null ) {
flatten(rootNode, flatNodes);
}
return flatNodes;
}
public void flatten(Node<String, Integer> node, List<Node<String, Integer>> flatNodes) {
Node<String, Integer> leftNode = node.left;
if ( leftNode != null ) {
flatten(leftNode, flatNodes);
}
flatNodes.add(node);
Node<String, Integer> rightNode = node.right;
if ( rightNode != null ) {
flatten(rightNode, flatNodes);
}
}
(6) The next bit is sorting the flat nodes list. Two implementations are presented, a more modern one which uses lambdas, and an older style one which uses an explicit comparator. The comparisons are written to generate a list sorted from smallest to largest. To reverse the sort order, exchange the order of comparison.
public void sort(List<Node<String, Integer>> nodes) {
Collections.sort(
nodes,
((Node<String, Integer> n1, Node<String, Integer> n2) -> Integer.compare(n1.value, n2.value)) );
}
public static final Comparator<Node<String, Integer>> NODE_COMPARATOR =
new Comparator<Node<String, Integer>>() {
public int compare(Node<String, Integer> n1, Node<String, Integer> n2) {
return Integer.compare(n1.value, n2.value);
}
};
public void sort(List<Node<String, Integer>> nodes) {
Collections.sort(nodes, NODE_COMPARATOR);
}
(7) Printing of the resulting sorted list is left as an exercise.
so i have a data structure project assignment , that i need to create singly linked list and implement a swing + exception handling concept.
I create a super market list item , but i am having a problem of restricting the user from entering duplicate ID-item , when user enters the duplicate it id , i wish to have a message " duplicate ID not allowed "
here is my code in the "frame" class
if(B==b11)
try
{
al1.AddItem(Integer.parseInt(t1.getText()),t2.getText(),Integer.parseInt(t4.getText()),Double.parseDouble(t5.getText()));
JOptionPane.showMessageDialog(null,"Added");
}
catch(Exception x){
JOptionPane.showMessageDialog(panel,"Wrong input ,please renter the fields ", "Warning",
JOptionPane.WARNING_MESSAGE);
};
and this is my code in the "Node process" class
public void AddItem(int ID, String Name, int Q, double P)
{
if(head==null)
head=tail=new project6(ID,Name,Q,P,head);
else
{
project6 pred, tmp;
for(pred = head, tmp = head.next; tmp != null && ID > tmp.ProductID; pred = pred.next, tmp = tmp.next);
if(tmp != null)
pred.next = new project6(ID,Name,Q,P,tmp);
else
tail.next = tail = new project6(ID,Name,Q,P, null);
}
}
If you are adding elements to a List, you can use the contains() method; if not, you should write a comparable method that traverses your Node data structure.
Alternatively, you might want to consider adding elements to a Set, which precludes duplicates. TreeSet may a good concrete implementation, as it remains ordered. The add() implementation returns false if the "set already contains the element." You can use that information to throw a suitable exception.
According to Wikipedia, regarding a trie:
Lexicographic sorting of a set of keys can be accomplished with a simple trie-based algorithm as follows:
Insert all keys in a trie.
Output all keys in the trie by means of pre-order traversal, which results in output that is in lexicographically increasing order.
However, this is my testing with my standard trie implementation:
Trie trie = new Trie();
trie.add("doll");
trie.add("ball");
trie.add("bat");
trie.add("dork");
trie.add("dorm");
trie.add("send");
trie.add("sense");
trie.add("sent");
Pre-order printout:
public List<String> allWords(){
List<String> words = new ArrayList<String>();
if(root == null){
return words;
}
StringBuilder prefix = new StringBuilder();
getAllWords(root.children,prefix,words);
return words;
}
// depth first search
private void getAllWords(List<TrieNode> children, StringBuilder prefix, List<String> words){
for(int i= 0; i<children.size(); i++){
TrieNode child = children.get(i);
if(!child.isWord_){
prefix.append(child.data_);
allWordsHelper(child.children, prefix, words);
}else{
prefix.append(child.data_);
words.add(prefix.toString());
}
prefix.deleteCharAt(prefix.length()-1);
}
}
And the output order is: doll dork dorm ball bat send sense sent
What does the 'lexicographic sorting' mean? It seems the output order is more related to the insertion order, not lexicographic order. Am I getting something wrong?
Take this tree as one example, the pre-order printout would be "to tea ted ten a inn". Where is the lexicographic order?
The correct way of saying about lexicographical sorting using tries is :
The preorder of the nodes in a trie is the same as the lexicographical order of the strings they represent assuming the children of a node are ordered by the edge labels.
Now, if you tried this in your code, pre-order traversal should give you strings in lexicographic order.
Here is the reference which has an example : http://www.cs.helsinki.fi/u/tpkarkka/opetus/12s/spa/lecture02.pdf
According to me, it should be Inorder traversal. One can traverse the trie such that all branches having keys less than root's value are processed first, then root's value is printed, and lastly all values greater than root's value. This is standard inorder traversal but the only point I wanted to make was, you will have to write custom logic for processing all branches having keys less than root's key first, which in a regular binary tree would just have been root.left, but since there is not left/right in trie we'll have to fall back on the essence of left and right in a BST.( whose inorder also outputs lexicographically sorted values.`)
Can Also be done by TreeMap -
import java.util.Map;
import java.util.TreeMap;
class TrieNodeTreeMap{
Map<Character, TrieNodeTreeMap> children;
String key;
public TrieNodeTreeMap(){
key = null;
children = new TreeMap<>();
}
}
public class LexicographPrint {
public static TrieNodeTreeMap root;
public static void main(String[] args) {
root = new TrieNodeTreeMap();
//String s = "lexicographic sorting of a set";
String s = "lexicographic sorting of a set of keys can be accomplished with " +
"a simple trie based algorithm we insert all keys in a trie output " +
"all keys in the trie by means of preorder traversal which results " +
"in output that is in lexicographically increasing order preorder " +
"traversal is a kind of depth first traversal";
String dict[] = s.split(" ");
for (String word : dict){
insertion(root,word);
}
lexicographlySort(root);
}
private static void insertion(TrieNodeTreeMap root, String str){
TrieNodeTreeMap curr = root;
for (char ch : str.toCharArray()){
if (!curr.children.containsKey(ch)){
curr.children.put(ch, new TrieNodeTreeMap());
}
curr = curr.children.get(ch);
}
curr.key = str;
}
private static void lexicographlySort(TrieNodeTreeMap root){
TrieNodeTreeMap curr = root;
if (curr == null)
return;
for (Map.Entry<Character, TrieNodeTreeMap> entry : curr.children.entrySet()){
TrieNodeTreeMap tmp = entry.getValue();
if (tmp.key != null)
System.out.println(tmp.key);
lexicographlySort(entry.getValue());
}
}
}
I have a binary search tree which stores objects. For inserting objects to it I am using Int value as a key. I get that value by calling method form the object like this:
public class Tree
{
// The root node of the tree which is null;
private Node root;
private double largest;
private Node insert (Node tree, Element d)
{
if (tree == null) return new Node(d);
else if (d.getPlaceInTable() < tree.data.getPlaceInTable()) tree.left = insert (tree.left, d);
else if (d.getPlaceInTable() > tree.data.getPlaceInTable()) tree.right = insert (tree.right, d);
return tree;
}
public void insert (Element d)
{
root = insert (root, d);
}
But what if I want to use Elements name as a key value which is string? How can I do it? Should I use compareTo() method? I know how to compare string1.compareTo(string2) but I really don' have any idea how I can use it in this case. If you have any suggestions, I really appreciate that.
Yes, String implements Comparable, so you can do
d.getName().compareTo(tree.data.getName()) < 0 for the left node and
d.getName().compareTo(tree.data.getName()) >= 0 for the right node
Also note, that in your original code you do not insert anything in your tree when values are equal.