请问版主和高手们。树的级别问题。

everloveit 2006-04-14 04:25:36

--A
---C
---E(1级)
---H(2级)
---X(3级)
---I
---F
---J(1代)
----K(2级)
----F
---D
--B
---U(1级)
---Y
---Z(2级)
---V

数据库结构是:
id parent_id title condition
1 0 A NULL
2 0 B NULL
3 1 C NULL
4 1 D NULL
5 3 E OK
6 5 H OK
7 6 X OK
8 3 F NULL
9 8 J OK
10 0 B NULL
11 10 U OK
12 11 Y NULL
13 12 Z OK

以上的树型结构中,注意:它们的级别,1、当达到条件时(condition为OK时),就为一级,2、以及:当第一次出现在节点中的树为第一级,第一级下的节点为第二级,
第二级下的节点为第三级,以此下去.......

这样的递归算法应该怎样写啊。要把上面有级别的会员找出来啊。

谢谢。。本人真的想不到好的办法,希望高手们可以帮忙。

TKS

...全文
239 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
everloveit 2006-04-20
  • 打赏
  • 举报
回复

感谢各位。我来试试。。
everloveit 2006-04-19
  • 打赏
  • 举报
回复
这是绑定树的递归函数。

没办法实现到找到树的级别啊。由于树在循环中不知道那些是第一次出现的级别。这些要怎么判断呢?注意:树的级别是这样的。

它们的级别,1、当达到条件时(condition为OK时),就为一级,2、以及:当第一次出现在节点中的树为第一级,第一级下的节点为第二级,
第二级下的节点为第三级,以此下去.......

有什么办法找到这些级别呢?

hax123 2006-04-19
  • 打赏
  • 举报
回复
应该是这个。

里面的objDsData 就是你的资料库
private Function AddTreeNode(byval strparentID as string)

dim objRow as datarow

For Each objRow In objDsData.Tables(0).Rows

if cstr(objRow.Item("parent_id") ) = strParentID then
这里自己写代码加树的结点。
-----------------
递归算法
AddTreeNode(objrow.item("id"))
---------------------

Endif

Next
End Function

差不多就是这样的了。你看看吧



End Function
hax123 2006-04-19
  • 打赏
  • 举报
回复
递归算法写

private Function AddTreeNode(byval strparentID,byval objDataset as dataset )

dim objRow as datarow

For Each objRow In objDsData.Tables(0).Rows

if cstr(objRow.Item("parent_id") ) = strParentID then
这里自己写代码加树的结点。
-----------------
递归算法
AddTreeNode(objrow.item("id"))
---------------------

Endif

Next
End Function

差不多就是这样的了。你看看吧



End Function
everloveit 2006-04-19
  • 打赏
  • 举报
回复
急啊。
我想在循环中读得
第一级:E(1级)、J(1代)、U(1级)
第二级:H(2级)、K(2级)、Z(2级)]
第三级: X(3级)

注意:我的要求,简单来说是压缩没有关系的树。

以上的树型结构中,注意:它们的级别,1、当达到条件时,就为一级,2、以及:当第一次出现在节点中的树为第一级,第一级下的节点为第二级,
第二级下的节点为第三级,以此下去.......

这样的递归算法应该怎样写啊。要把上面有级别的会员找出来啊。

谢谢。。本人真的想不到好的办法,希望高手们可以帮忙。

TKS
hax123 2006-04-19
  • 打赏
  • 举报
回复
好像我写的正好是倒过来的。。。。变成3,2,1了,
楼主理解一下这个算法,处理方法一样的,
只要反过来把级别变为子目录的加就行了。
hax123 2006-04-19
  • 打赏
  • 举报
回复
Private Sub AddTreeNode1(ByVal objRow As DataRow, ByRef objHash As Hashtable)

Dim objRowChild As DataRow
Dim bolHasChild As Boolean = False
Dim strID As String = ""

If Not objRow Is Nothing Then
strID = CStr(objRow.Item("ID"))
Else
strID = ""
End If

For Each objRowChild In Me._objDs.tblGenLedger

If CStr(objRowChild.Item("parent_id")) = strID Then
bolHasChild = True
objRowChild.Item("Level") = 1
AddTreeNode1(objRowChild, objHash)
End If

Next

If bolHasChild Then
If Not objRow Is Nothing Then
If Not objHash.Contains(objRow.Item("ID")) Then
objRow.Item("Level") = CInt(objRow.Item("Level")) + 1
objHash.Add(objRow.Item("ID"), objRow.Item("ID"))
End If
End If
End If

End Sub

抱歉,上面的没有判断是否已经加级别。正确的应该是用这个。
hax123 2006-04-19
  • 打赏
  • 举报
回复
Private Sub AddTreeNode1(ByVal objRow As DataRow)

Dim objRowChild As DataRow
Dim bolHasChild As Boolean = False
Dim strID As String = ""

If Not objRow Is Nothing Then
strID = CStr(objRow.Item("ID"))
Else
strID = ""
End If

For Each objRowChild In Me._objDs.tblGenLedger

If CStr(objRowChild.Item("parent_id")) = strID Then
bolHasChild = True
objRowChild.Item("Level") = 1
AddTreeNode1(objRowChild)
End If

Next

If bolHasChild Then
If Not objRow Is Nothing Then
objRow.Item("Level") = CInt(objRow.Item("Level")) + 1
End If
End If

End Sub

用这个,上面多传了些没用的参数
vfan2010 2006-04-19
  • 打赏
  • 举报
回复
可以根据ID的长度来判断。这就需要你把每个的ID设为一个比较合适的长度了。
http://blog.sina.com.cn/u/3e4c565b010003aa
看看这篇文章里面的数据库的ID是怎么组织的,到时候你可以根据不同的长度来判断了。希望对你有所启发。
hax123 2006-04-19
  • 打赏
  • 举报
回复
Private Sub AddTreeNode1(ByVal objRow As DataRow, ByRef intChildCount As Integer)

Dim objRowChild As DataRow
Dim bolHasChild As Boolean = False
Dim strID As String = ""

If Not objRow Is Nothing Then
strID = CStr(objRow.Item("ID"))
Else
strID = ""
End If

For Each objRowChild In Me._objDs.tblGenLedger

If CStr(objRowChild.Item("parent_id")) = strID Then
bolHasChild = True
objRowChild.Item("Level") = 1
AddTreeNode1(objRowChild, intChildCount)
End If

Next

If bolHasChild Then
If Not objRow Is Nothing Then
objRow.Item("Level") = CInt(objRow.Item("Level")) + 1
End If
End If

End Sub

你理解一下这个。
大概就是我们默认的级别都为一级,
当我们发现有下级目录时,自动把自己的级别加1,
lee_wei 2006-04-19
  • 打赏
  • 举报
回复
递归的算法,以下是我个人使用到的,希望能有帮助:
/// <summary>
/// 获取树状区域酒店列表
/// </summary>
private void ShowHotelTreeList()
{
Tree_HotelList.Nodes.Clear();

//获取所有区域
regionDt = hotel.GetRegionById(Session["userRegionId"].ToString());
//获取所有酒店
hotelDt = hotel.GetHotelsByRegionId(Session["userRegionId"].ToString());

//调用递归函数,生成树状结构
AddMenuItem("0", (TreeNode)null);

//判断是否有Session["hotelNodeIndex"]
//判断是否有url参数nodeId
if (hasSession || hasUrlParm)
{
Tree_HotelList.SelectedNodeIndex = Session["hotelNodeIndex"].ToString();
}
}

/// <summary>
/// 递归添加菜单的节点,包括区域,酒店
/// </summary>
/// <param name="pId">父节点Id</param>
/// <param name="pNode">父节点</param>
private void AddMenuItem(string pId, TreeNode pNode)
{
//是否第一次加载,第一次加载pNode==null
if (pNode == null)
{
DataRow dr = regionDt.Rows[0];

TreeNode node = new TreeNode();
node.Text = dr["Name"].ToString();
node.ID = "R" + dr["Id"].ToString();
node.ImageUrl = "../Images/hotel/Region.gif";
node.ExpandedImageUrl = "../Images/hotel/RegionEx.gif";
Tree_HotelList.Nodes.Add(node);
node.Expanded = true;

AddMenuItem(node.ID.Substring(1), node);
}
else
{
//遍历Region
DataView regionView = new DataView(regionDt);
regionView.RowFilter = String.Format("ParentId = '{0}'", pId);

foreach (DataRowView dr in regionView)
{
TreeNode node = new TreeNode();
node.Text = dr["Name"].ToString();
node.ID = "R" + dr["Id"].ToString();
node.ImageUrl = "../Images/hotel/Region.gif";
node.ExpandedImageUrl = "../Images/hotel/RegionEx.gif";
pNode.Nodes.Add(node);
node.Expanded = true;
//判断url参数nodeId是否当前节点
GetSelectedNodeIndex(node);

AddMenuItem(node.ID.Substring(1), node);
}

//遍历Hotel
DataView hotelView = new DataView(hotelDt);
hotelView.RowFilter = String.Format("RegionId = '{0}'", pId);

foreach (DataRowView dr in hotelView)
{
TreeNode node = new TreeNode();
node.Text = dr["HotelName"].ToString();
node.ID = "H" + dr["HotelId"].ToString();
//判断该酒店的当前状态
node.ImageUrl = ((Convert.ToBoolean(dr["IsConnecting"])) ? "../Images/hotel/connecting.gif" : "../Images/hotel/stop.gif");
pNode.Nodes.Add(node);
node.Expanded = true;
//判断url参数nodeId是否当前节点
GetSelectedNodeIndex(node);
}
}
}
lee_wei 2006-04-19
  • 打赏
  • 举报
回复
前两天刚刚接触了无限级树状菜单的生成,我个人觉得Id,parentId的格式对于维护整个菜单起到很重要的作用。
比如说:
福建
--福州
--仓山
--鼓楼
--厦门
表中记录:
Name Id ParentId
福建 00 NULL
福州 0001 00
厦门 0002 00
仓山 000101 0001
鼓楼 000102 0001

这样的结构不管对于生成菜单,还是移动,删除都是相当方便的,欢迎讨论
www.leewei.cn
hax123 2006-04-19
  • 打赏
  • 举报
回复
我们是不是可以定义一个HashTable,用来保存已经读取过的树的ID呢?
这样就可以知道上级是否已经读取了
everloveit 2006-04-19
  • 打赏
  • 举报
回复
树的深度我有的啊。即系layer次罗1、2、3。从根目录开始的。
但在读取到第一级后,再读取到第二级时,怎样判断呢上级已经读取过呢?
因为不是每layer机同的就是同一级。是由于级同layer层唔同啦。不规则的。
所以在循环时很难判断。请给出最优的算法。

TKS
hax123 2006-04-19
  • 打赏
  • 举报
回复
你可以加一个字段记录树的深度,这样你就可以找到了。
之后你根据深度来判断根是哪个级别的了
hax123 2006-04-19
  • 打赏
  • 举报
回复
你是否要从根目录开始往回加树?
hax123 2006-04-19
  • 打赏
  • 举报
回复
你是否可以加一个字段为indent
这个可以做为树的级别来用。
当第一次时为1,第二子树的就为2,这样是否可以呢?
everloveit 2006-04-17
  • 打赏
  • 举报
回复
DataRow [] drParent = dataset.Tables["TREE"].Select("depth=" + depth + 1 + " );
foreach( DataRow r in drParent )
{
...
}

try.....
Jianyi 2006-04-15
  • 打赏
  • 举报
回复
数据库结构:
id parent_id title condition depth

depth放置深度,在插入数据时就算好(等于父节点depth+1)
everloveit 2006-04-15
  • 打赏
  • 举报
回复
up
加载更多回复(7)

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧