how do I change the order of treenodes - c#

I would like to change the order of System.Windows.Forms.TreeNodes on the same level.
any suggestions on how this might be done in .net-2.0.

You need to manipulate the TreeView's Nodes collection. See TreeNodeCollection.
If you have three tree nodes and you want to move the last one to the front, for example: (Note: not tested code, but shows the idea)
var lastNode = MyTreeView.Nodes[2];
MyTreeView.Nodes.Remove(lastNode);
MyTreeView.Nodes.Insert(0, lastNode);

void MoveNodeUp(TreeNode node)
{
TreeNode parentNode = node.Parent;
int originalIndex = node.Index;
if (node.Index == 0) return;
TreeNode ClonedNode = (TreeNode)node.Clone();
node.Remove();
parentNode.Nodes.Insert(originalIndex - 1, ClonedNode);
parentNode.TreeView.SelectedNode = ClonedNode;
}

That's what I've written:
public void MoveNode(TreeView tv, TreeNode node, bool up)
{
if ((node.PrevNode == null) && up) {
return;
}
if ((node.NextNode == null) && !up) {
return;
}
int newIndex = up ? node.Index - 1 : node.Index + 1;
var nodes = tv.Nodes;
if (node.Parent != null) {
nodes = node.Parent.Nodes;
}
nodes.Remove(node);
nodes.Insert(newIndex, node);
}

I wrote this code which does not require any cloning.
For my case it moves up one position in the sibling nodes but can be adapted
TreeNode selectedNode = treeViewChain.SelectedNode;
if (selectedNode != null && selectedNode.Index > 0)
{
TreeNode parent = selectedNode.Parent;
int selectedIndex = selectedNode.Index;
selectedNode.Remove();
parent.Nodes.Insert(selectedIndex - 1, selectedNode);
treeViewChain.SelectedNode = selectedNode;
}

Related

Binary-Search-Tree's remove function doesn't work for 2 child nodes

I'm learning about Binary Search Trees and Recursion. I'm able to get expected results with leaf and single child nodes. However, whenever I try to delete a node with 2 child nodes but am not receiving the expected result. When deleting the rootNode (12), How is it possible that the rootNode is being set as 18... since 18 is the value of the root's right child's right node?
/* Using Pre-Order Traversal
* Original Tree: [12,7,3,7,14,18]
* Expected Result: [14,7,3,7,18]
* Result Tree: [18,7,3,7,18] */
public void DeleteNode(Node rootNode, int deleteValue)
{
SearchBinaryTree(DeleteNodeHelper, rootNode, deleteValue);
}
public void DeleteNodeHelper(Node node)
{
if(node != null)
{
// 0 child? unlink the node from its parent
if (node.Left == null && node.Right == null)
{
node.Value = 0;
node.Name = "deleted";
node.Left = null;
node.Right = null;
}
// 2 child? replace root node with right child's left-most value
if (node.Left != null && node.Right != null)
{
Node rootNodeReplacement = FindLeftMostNode(node.Right);
SearchBinaryTree(DeleteNodeHelper, node.Right, rootNodeReplacement.Value);
node.Value = rootNodeReplacement.Value;
}
//1 child? replace root node with only child
else
{
node.Value = node.Left != null ? node.Left.Value : node.Right.Value;
node.Name = node.Left != null ? node.Left.Name : node.Right.Name;
node.Left = null;
node.Right = null;
}
}
}
public void SearchBinaryTree(Action<Node> action, Node node, int searchValue)
{
if (node != null)
{
if ( node.Value == searchValue)
{
action.Invoke(node);
}
if (node.Value < searchValue)
{
SearchBinaryTree(action, node.Right, searchValue);
}
if (node.Value > searchValue)
{
SearchBinaryTree(action, node.Left, searchValue);
}
}
}
public Node FindLeftMostNode(Node node)
{
while (node.Left != null)
{
node = node.Left;
}
return node;
}
Figured it out. I had two lines of code swapped. I tried to delete the right-child's left-most node before I updated the root node.
public void DeleteNodeHelper(Node node)
{
if (node != null)
{
// 0 child? unlink the node from its parent
if (node.Left == null && node.Right == null)
{
node.Value = 0;
node.Name = "deleted";
node.Left = null;
node.Right = null;
}
// 2 child? replace root node with right child's left-most value
if (node.Left != null && node.Right != null)
{
Node rootNodeReplacement = FindLeftMostNode(node.Right);
node.Value = rootNodeReplacement.Value; //this line was swapped with the one below
SearchBinaryTree(DeleteNodeHelper, node.Right, rootNodeReplacement.Value);
}
//1 child? replace root node with only child
else
{
node.Value = node.Left != null ? node.Left.Value : node.Right.Value;
node.Name = node.Left != null ? node.Left.Name : node.Right.Name;
node.Left = null;
node.Right = null;
}
}
}

Linked list first and last element can't be deleted

I made big research in this forum and found many "solutions" but none of them work.
Maybe my situation is a little bit different and I maybe someone can see where is the problem. I need to delete each Node element which is has "value" less than given(kruvis).
public void Delete()
{
if (Start == null) return;
if (Start.Next == null)
{
Start = null;
return;
}
if (Current.Next == null)
{
Current = null;
}
Node temp = Start;
while (temp.Next.Next != null)
{
if (temp.Next == Current)
{
temp.Next = Current.Next;
Current = temp;
return;
}
temp = temp.Next;
}
}
There is another function(loop in function) in diferent class
for (MenesioAgentai.Pradzia(); MenesioAgentai.ArYra(); MenesioAgentai.Sekantis())
{
if (MenesioAgentai.GautiT().Kruvis <= kruvis)
{
kruvioSuma += MenesioAgentai.GautiT().Kruvis;
PasalintiAgentoPrenumeratorius(pren, MenesioAgentai.GautiT());
MenesioAgentai.Delete();
}
}
The problem is that the first and last element is not deleted
in NodeList class I have 3 nodes Start, End, Current. (and sealed class Node with T data and Node Next)
Deleting node from a linked list is a bit tricky when the head node also needs to be deleted. An easier way is to add a sentinel node at the beginning. The following Java code explains how to delete nodes that have a smaller value than a given value. I used a value of type int for simplicity.
/*
// Node definition
class Node {
Node next;
int val;
Node(int val) {
this.val = val;
}
}
*/
public Node delete(Node head, int k) {
Node sentinel = new Node(Integer.MIN_VALUE);
sentinel.next = head;
Node prev = sentinel, curr = sentinel.next;
while(curr != null) {
while(curr != null && curr.val < k) {
curr = curr.next;
}
prev.next = curr;
prev = curr;
if(curr != null) {
curr = curr.next;
}
}
return sentinel.next;
}

How to set position while traversing through Treeview

I want to traverse through a treeview & set the value property to be its position in the tree as shown below
A[val:1]->A1[val:11]
l l--->A2[val:12]
l----->A3[val:13]
B[val:2]->B1[val:21]
l l--->B2[val:22]
C[val:3]->C1[val:31]
l l--->C2[val:32]
I have written a recursive which returns me all the nodes but i am unable to assign the desired position to its nodes.
private void TraverseTreeNode(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
TraverseTreeNode(node.ChildNodes);
}
}
Considering that TreeNode.Value is of type string, this will, starting at level = 1:
private static void TraverseTreeNode(TreeNodeCollection nodes, int parentNumber)
{
var childNumber = 1;
foreach (TreeNode node in nodes)
{
node.Value = string.Format("{0}{1}", parentNumber, childNumber ).Substring(0,node.Depth+1);
TraverseTreeNode(node.ChildNodes, parentNumber);
childNumber++;
if (node.Depth == 0) { parentNumber++; }
}
}
Only works for two levels but is easily extendable by adding additional parameters to TraverseTreeNode.
UPDATE
The following will work for any depth in hierarchy:
private static void TraverseTreeNode(TreeNodeCollection nodes, int parentNumber)
{
var childNumber = 1;
foreach (TreeNode node in nodes)
{
node.Value = node.Parent != null && node.Parent.Value != null
? string.Format("{0}{1}", node.Parent.Value, childNumber)
: string.Format("{0}{1}", parentNumber, childNumber).Substring(0, node.Depth + 1);
TraverseTreeNode(node.ChildNodes, parentNumber);
childNumber++;
if (node.Depth == 0) { parentNumber++; }
}
}
As you need recursive method, try this
private void Caller()
{
TraverseTreeNode(treeView1.Nodes);
}
private void TraverseTreeNode(TreeNodeCollection nodes)
{
int index = 1;
foreach (TreeNode node in nodes)
{
node.Text = (node.Parent != null ? node.Parent.Text : string.Empty) + index++;
TraverseTreeNode(node.Nodes);
}
}

how to get the second level text from the leaf?

How to get the second father if my position was the leaf .
for example :
1---->2---->3
or
1---->2---->3---->4
or
1---->2---->3---->4---->5
if i'm in the last node (3 or 4 or 5)
How to get the text of node (2)?
foreach (RadTreeNode node in nodeCollection)
{
if (node.Nodes.Count == 0)//leaf
{
if (!node.Value.TrimEnd().Contains('#'))
{
GroupDetails grp_d = new GroupDetails();
grp_d.Boss_code = 0;
grp_d.Boss_name = string.Empty;
if (node.Value.TrimEnd().Split('_').Count() > 2)
{
grp_d.Boss_code = int.Parse(node.Value.TrimEnd().Split('_')[2]);
grp_d.Boss_name = node.Value.TrimEnd().Split('_')[3];
}
grp_d.Dep_code = int.Parse(node.Value.TrimEnd().Split('_')[0]);
grp_d.Dep_name = node.Text.TrimEnd() //Here i want to get the second parent text to concatenate
grp_d.Dep_year = int.Parse(node.Value.TrimEnd().Split('_')[1]);
grp_d.Group_id = res;
grp_det.Add(grp_d);
}
}
}
while( node.parent != null )
node = node.parent;
return node.child;
Assuming you only have one child (i.e. node (2))
Just suggesting a logical way of traversing the tree. Implementation is up to you and your system design!
RadTreeNode node_tmp = new RadTreeNode();
node_tmp = node;
while (node_tmp.ParentNode != null)
{
p_txt = node_tmp.Text.TrimEnd();
node_tmp = node_tmp.ParentNode;
}

Get next item in a tree

Having a tree (logical in DB) with items in the form
List item A
List item B
List item C
List item D
List Item E
List Item F
List Item G
and so on (nesting depth not limited), I want to get the next node down (or up), starting from an arbitrary node.
Let's say, List Item D is given I want to write a function GetNextNode() that would return List Item E.
My idea would be to do some recursion stuff, but maybe there is a more clever way to handle this?
My question:
How would you solve this?
EDIT 1:
The tree can be accessed with functions like:
GetParentNode()
GetChildrenNodes()
GetNextSiblingNode()
etc.
So it's similar to e.g. e Windows Forms TreeView.
I've had to do this several times. From memory:
public Node GetBelowNode()
{
if (GetChildrenNodes().count > 0)
return GetChildrenNodes()[0];
else
if (GetNextSiblingNode() != null)
return GetNextSiblingNode();
else
{
Node curr = this;
Node parent;
while (true)
{
parent = curr.GetParentNode();
if (parent == null)
return null;
else
{
if (parent.GetNextSiblingNode() != null)
return parent.GetNextSiblingNode();
else
curr = parent;
}
}
}
}
You can handle this via recursion or... worst xD
I think there are only 3 basic cases:
private string getNext(TreeNode node)
{
if (node.FirstNode != null)
{
return node.FirstNode.Name;
}
else
{
if (node.NextNode != null)
{
return node.NextNode.Name;
}
else if (node.Parent.NextNode != null)
{
return node.Parent.NextNode.Name;
}
}
return "";
}
This doesn't works for every scenario. You should search the parent's next node too. Thanks to Vincent Vancalbergh for the comment ;-)
public Party Next {
get {
if (this.children.Count > 0) return this.children[0];
Party target = this;
do {
if (target.NextSibling != null) return target.NextSibling;
} while ((target = target.Parent) != null);
return null;
}
}
public Party Previous {
get {
if (Parent != null && Parent.children.Count > 0 && this == Parent.children[0]) {
return Parent;
}
Party target = this;
do {
if (target.PreviousSibling != null) { target = target.PreviousSibling; break; }
} while ((target = target.Parent) != null);
if (target != null) {
while (target.children.Count > 0) {
target = target.children[target.children.Count - 1];
}
}
return target;
}
}
Since I got a great reply for the "down" part, I'll added my own "up" part. Maybe it is for some help of you; the up part is similar to:
Get the previous sibling.
If there is a previous sibling, get the deepest child node of this
sibling.
If there is no previous sibling, get the direct parent.
To get the deepest sibling (2.), I use the following code:
function getDeepestChild( page )
dim result
set result = nothing
dim childPages
set childPages = page.ChildPages
if childPages.Count>0 then
dim p
set p = childPages(childPages.Count-1)
' recurse.
set result = getDeepestChild( p )
else
set result = page
end if
set getDeepestChild = result
end function
(Yes, I do know that this is VBScript; I needed it in fact in this language)
Try this maybe:
TreeNode currentNode = treeView1.SelectedNode;
treeView1.selectedNode = currentNode.NextNode;

Categories