type struct Node {
x Data
l *Node
r *Node
}
Given the struct above, I am working on various implementations of binary search trees, all within the same package so that they can share internals without a public interface. However, some trees require a rank field as part of their node, which I would like to create as an extension of the base struct. I do not want the trees that do not require a rank field to allocate a node with a rank field.
type struct RankedNode {
Node
z rank
}
At first, this seems correct and communicates clear intent to me. However, this does not work because the internal l and r fields are of type Node, breaking code like this:
func (p *RankedNode) heapify() *RankedNode {
// ...
p.l.heapify()
p.r.heapify()
}
Of course, p.l and p.r are of type Node, so heapify is not defined. We can make the assumption that any node can only be linked to nodes of the exact same type.
Q: Is a Node interface and type assertions the only way to achieve this without generics?
func (p *RankedNode) heapify() *RankedNode {
// ...
p.L().(*RankedNode).heapify()
p.R().(*RankedNode).heapify() // :(
}
Related
I’ve been trying to query XML with the sxd-xpath crate and I can’t seem to figure out how to handle a nodeset.
Crate and using
extern crate sxd_document;
extern crate sxd_xpath;
use sxd_document::parser;
use sxd_xpath::{Factory, Context, Value};
Actual code
let package = parser::parse("<feed><title>hest</title><title>hest2</title><title>hest3</title><title>hest4</title></feed>").expect("failed to parse XML");
let document = package.as_document();
let factory = Factory::new();
let xpath = factory.build("/feed/title").expect("Could not compile XPath");
let xpath = xpath.expect("No XPath was compiled");
let context = Context::new();
let value = xpath.evaluate(&context, document.root()).expect("XPath evaluation failed");
I would like to iterate over every node and print out the value of <title>, but I do not understand how to do it.
I’m fairly new in the Rust world, coming from C# and Python.
XPath::evaluate returns a Value:
fn evaluate<'d, N>(
&self,
context: &Context<'d>,
node: N,
) -> Result<Value<'d>, ExecutionError>
where
N: Into<Node<'d>>,
A Value is an enumeration of the possible values of an XPath (a number, a boolean, a string, or a nodeset). In your case, you are interested in a nodeset, so you will want to match on that variant:
if let Value::Nodeset(nodes) = value {
// ...
}
Nodeset implements IntoIterator, so you can use it in a for loop:
for node in nodes {
// ...
}
Each yielded value will be a Node. This is an enumeration of all the different types of nodes in an XML document. You are interested in Elements. If all you care about is the string value of the element, you can use Node::string_value. This hides away any complexities of multiple child nodes each with their own text:
println!("{}", node.string_value());
Put all together:
if let Value::Nodeset(nodes) = value {
for node in nodes {
println!("{}", node.string_value());
}
}
A Nodeset doesn't have a guaranteed order, so if you want the nodes in the order that they come from in the document, you can call Nodeset::document_order:
if let Value::Nodeset(nodes) = value {
for node in nodes.document_order() {
println!("{}", node.string_value());
}
}
Disclaimer: I am the author of SXD-Document and SXD-XPath
I have a very specific problem, I cannot figure out a solution for.
I have a map[string]Metric, which I want to convert into a tree for using in a frontend. The Metric interface looks has a Path() and a Name() Method, the name method returns the last part of a period-separated path (so a path of 'my.awesome.metric' will mean that this metric has the name 'metric')
The tree should be sorted by the path and should contain IndexNodes. This struct looks like this:
type IndexNode struct {
Name string
Path string
Children []*IndexNode
}
So a map like this:
{
my.awesome.metric.downloads
my.awesome.othermetric.downloads
my.awesome.othermetric.uploads
my.other.cool.metric
}
Should lead to a tree like this: (sorry for the crude ascii art)
+-- other -- cool -- metric
|
my --+ +-- metric -- downloads
| |
+-- awesome --+ +-- downloads
| |
+-- othermetric --+
|
+-- uploads
Note that I only ever have one root node (my in this case). The order inside of the tree does not matter to me.
I tried my best and cannot figure it out... After lots of googleing (which only showed me how to create binary search trees and the GoDS library), I resigned and decided to ask my very first question here 😊
Thanks for your help!
Change Children to map[string]*IndexNode and you are halfway there. If you don't mind it being a lot slower to look stuff up, you can use a slice, but this means you need to search the slice to find the child you want every time you traverse the tree. A map is faster and easier in this case.
Now you just need to write a recursive function that steps down the tree, making nodes as needed for each element in the path until it reaches the end.
Unfortunately I don't have ready access to an example, all my code in on my other computer :(
A quick and dirty example:
type Tree struct {
Parent *Tree
Children map[string]*Tree
Payload bool // Your data here
}
func NewTree(parent *Tree, path []string, payload bool) *Tree {
if parent == nil {
parent = &Tree{nil, map[string]*Tree{}, false}
}
if len(path) == 0 {
parent.Payload = payload
return parent
}
child := parent.Children[path[0]]
if child == nil {
child = &Tree{parent, map[string]*Tree{}, false}
parent.Children[path[0]] = child
}
return NewTree(child, path[1:], payload)
}
Usage:
root := NewTree(nil, nil, false)
newnode := NewTree(root, []string{"A", "B", "C"}, true)
Try it on the Go Playground!
Here's a solution using a map, traversing it can help you populate the data structure. Can create the nodes where it says "Parent xxx Child xxx" in the tree navigation https://play.golang.org/p/sVqBCVgiBG
When I tried to practice some basic data structure such as Linked /Doubly Linked/ Recycling Linked / Recycling Doubly Linked List, AVL Tree, Red-Black Tree, B-Tree and Treap by implementing them in Swift 2, I decided to do such things by taking advantage of Swift 2's new feature: indirect enum, because enum makes an empty node and a filled node more semantic than class.
But soonish it was found that for non-recycling linked lists, returning the inserted node after inserting an element makes no sense because the returned value is a value type but not a reference type. It is said that you cannot accelerate next insertion by writing information directly to the returned value because it is a copy of the inserted node but not a reference to the inserted node.
And what's worse is that mutating an indirect enum based node means writing the whole bunch of data of the associative value, which definitively introduces unnecessary system resource consumption, because the associative value in each enum case is a tuple in essence, which is a sort of contiguous data in memory in essence, which is the same to struct but doesn't have per property accessor to enable small bunch of data writing.
So which one should I use for building such basic data structures? Indirect enum or class?
Well it doesn't matter if it's swift 1 or swift 2 cause at the moment Enum and Structures are value types while Classes are called by reference. Since you want to use data structures in your code and like you called it yourself calling them by value is no good. You will have to use a Class in order for your code to do what you want it to do. Here is an example of a linked list using a Class:
class LLNode<T>
{
var key: T? var next: LLNode? var previous: LLNode?
}
//key printing
func printAllKeys()
{
var current: LLNode! = head; //assign the next instance
while(current != nil)
{
println("link item is: \(current.key)")
current = current.next
}
}
public class LinkedList<T: Equatable>
{ //create a new LLNode instance private
var head: LLNode<T> = LLNode<T>() //append a new item to a linked list
func addLink(key: T)
{ //establish the head node
if (head.key == nil)
{
head.key = key;
return;
} //establish the iteration variables
var current: LLNode? = head
while (current != nil)
{
if (current?.next == nil)
{
var childToUse: LLNode = LLNode<T>()
childToUse.key = key;
childToUse.previous = current
current!.next = childToUse;
break;
}
current = current?.next
} //end while
} ///end function
for more examples using swift and data structures please do visit:
data structures swift
Conclusion : Use Class if you want to call by reference else use Enum or Struct
I have this code
tree match {
case EmptyNode =>
//do stuff with empty node
case Node(left, right, value) =>
//do stuff with node contents
}
However what if I want to update the value of a node? I tried doing value = newValue inside the case, but it doesn't seem to be allowed.
Structure of my trees/nodes:
sealed trait Tree
case class Node(var left: Tree, var right: Tree, var value: String) extends Tree
case object EmptyNode extends Tree
You can reference the actual node with # notation:
case n#Node(left, right, value) => n.value = "newValue"
Noah's answer does show the way to change the value of the node, but you shouldn't do that. One of the main ideas of scala is to promote immutable data structures, i.e. once you define an object, you don't change it.
This is particularly important in a tree, because by changing the value of the node, you are potentially making your tree inconsistent (values to the left of the node may no longer be smaller). Instead, always keep nodes values immutable and add or delete nodes as needed, minding rebalancing of the tree when a node is deleted.
the other day I made a quick tool to figure out exactly what the question asked but with a fixed range, which works well just by using a stupid amount of for loops but I would like to make it work for a use definable range.
The data structure in looks like
Where each node can link to any other number of nodes and can all link back to itself it you follow the right path(Which tended to break my implementations).
It's just defined as
type Node struct {
Name string
ID int
}
And you can get a list of nodes it is linked with using a method which returns a slice of Nodes which gets the information from a database with around 5,000 entries.
Initially I tried some stuff with recursion which just ended up with me having a hurt head and code that just doesn't work. I just can't seem to get my head around this.
Thanks in advance, and if this type of data has a specific name I would love to know what it is!
My final code looked something like this
func rec(x Node, depth int) Node {
s := make([]Node, 0)
if depth == 0 {
s = append(s, x)
} else {
for _, y := range x.Get() {
s = append(s, rec(y, depth-1)...)
}
}
return s
}
and it worked wonderfully. Thanks a lot to siritinga for pointing me in the right direction.