JSP无限分类的具体实现,怎么能自动判断所属的父级分类

hmilyld 2007-05-03 03:07:47
表中三个字段
id name childid
1 根目录1 0
2 根目录2 0
3 子目录1 1
4 子目录2 1
5 子目录3 2
6 子目录4 2
…………

ID自动生成的,
childid就是 属于哪个的子分类,就是那个分类的ID编号,
从数据库读回来内容后,
怎么能对他实现自动分类呢,归属哪个类别就在哪个类别的下面.
也就是对分类实现能够无限分类,
查了下,都说用递归实现,
谁能给个例子看下吗,
从数据库查回来内容以后就不会弄了,郁闷.
...全文
732 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
hmilyld 2007-05-09
  • 打赏
  • 举报
回复
/**
* 功能:对栏目进行无限级分类
* 数据库表说明:
* id:自动编号
* name:栏目名称
* parentid:所属父级栏目编号,与id相对应
* @author Hmilyld
* @home http://www.hmilyld.cn
*/
package com.hmilyld.channel;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import com.hmilyld.study.DatabaseBean;

public class ChannelBean {
Connection conn;

static Collection<Channel> rs = new ArrayList<Channel>(); //静态Collection,只存在一份rs,不需要每次都对数据库进行查询,提高效率

/*
* 得到Connection连接
*/
public ChannelBean() {
try {
this.conn = DatabaseBean.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
}

/*
* 查库,得到库中所有分类,返回Collection
*/
public Collection getChannel() throws SQLException {
Statement stm = conn.createStatement();
ResultSet rst = stm.executeQuery("select * from channel");
while (rst.next()) {
Channel channel = new Channel();
channel.setChannelId(rst.getInt("id"));
channel.setChannelName(rst.getString("name"));
channel.setChannelParentId(rst.getInt("parentid"));
rs.add(channel);
}
conn.close();
return rs;
}

public static void main(String[] args) throws Exception {
ChannelBean channel = new ChannelBean();
channel.getChannel();
Iterator it = ChannelBean.rs.iterator();
while (it.hasNext()) {
Channel chan = (Channel) it.next();
if (chan.getChannelParentId() == 0) {
int i = chan.getChannelId();
System.out.println(chan.getChannelName()); // 打印出最顶级分类
/*
* 打印出顶级分类下的分类,然后调用channelSort,传递栏目名称
*/
ChannelBean.channelSort(it, i ,chan.getChannelName());
}
}
}
/*
* 循环得到分类方法
*/
public static void channelSort(Iterator it, int id ,String name) throws Exception {
it = ChannelBean.rs.iterator();
while (it.hasNext()) {
Channel chan = (Channel) it.next();
int channelChildId = chan.getChannelParentId();
int channelId = chan.getChannelId();
if (channelChildId == id) {
System.out.println(name+"--" + chan.getChannelName());
String na = name+"--"+chan.getChannelName();
/*
* 循环调用获取分类名称
*/
channelSort(it, channelId ,na);
}
}
}
}


又换了下,不过你说那个用堆栈的方式,不是太明白.呵呵.:)
先结贴吧,暂时搞定勒,虽然效率低了点
kaoloveting 2007-05-05
  • 打赏
  • 举报
回复
mark
林二棍子 2007-05-05
  • 打赏
  • 举报
回复
……不好意思,上面错了……我汗啊汗
public void printChannel(int level, int parentId) {
Stack stack = new Stack();// 我忘记堆栈的实现类是哪个了
int pid = parentId;
for(Iterator iter=this.getChannel().iterator(); iter.hasNext();) {
Channel channel = (Channel) iter.next();
while(pid != channel.getParentId() && !stack.isEmpty())
// 当前pid已没有子节点,从stack出栈
pid = ((Integer) stack.pop()).intValue();
level--;
}
// 打印
for(int i=0; i<level; i++) {
System.out.print("-");
}
System.out.println(channel.getName());
// 把pid入栈,用当前id替换
stack.push(new Integer(pid));
pid = channel.getChannelId();
level++;
}
}
林二棍子 2007-05-05
  • 打赏
  • 举报
回复
这种方式的时间复杂度是n*n,所以确实效率很低。如果你用了CONNECT BY那句,时间复杂度可以降低,但是要使用堆栈,只要改写printChannel:

public void printChannel(int level, int parentId) {
Stack stack = new Stack();// 我忘记堆栈的实现类是哪个了
int pid = parentId;
for(Iterator iter=this.getChannel().iterator(); iter.hasNext();) {
Channel channel = (Channel) iter.next();
if(channel.getParentId()==pid) {
for(int i=0; i<level; i++) {
System.out.print("-");
}
System.out.println(channel.getName());
} else {
while(pid != channel.getParentId() && !stack.isEmpty())
// 当前pid已没有子节点,从stack出栈
pid = ((Integer) stack.pop()).intValue();
level--;
}
}
// 打印
for(int i=0; i<level; i++) {
System.out.print("-");
}
System.out.println(channel.getName());
// 把pid入栈,用当前id替换
stack.push(new Integer(pid));
pid = channel.getChannelId();
level++;
}
}
林二棍子 2007-05-05
  • 打赏
  • 举报
回复
首先你在main方法中调用了getChannel()方法,已经把所有的分类的取到了。这个时候你应该把List保存起来,而不是每次都到数据库中取。

public class ChannelBean {

private Collection<Channel> channelList = null;

public Collection getChannel() throws SQLException {
if(this.channelList==null) {
channelList = new ArrayList<Channel>();
//原来的哪些,不要return
//建议你用我前面回复的那个SQL语句,取得的结果集已经排序过了
...
conn.close();
}
return channelList;
}

public static void main(String[] args) {
ChannelBean bean = new ChannelBean();
channelBean.printChannel(0, 0);
}

// 打印
// 不按我的SQL语句排序的情况
public void printChannel(int level, int parentId) {
for(Iterator iter=this.getChannel().iterator(); iter.hasNext();) {
Channel channel = (Channel) iter.next();
if(channel.getParentId()==parentId) {
for(int i=0; i<level; i++) {
System.out.print("-");
}
System.out.println(channel.getName());
// 递归调用
printChannel(level + 1, channel.getChannelId());
}
}
}
}
hmilyld 2007-05-05
  • 打赏
  • 举报
回复
可能开始想要描述的不怎么清楚,还有就是childid这个也写错了,应该是他的父级分类,parentid,不是childid的,呵呵。
我自己这样写了一个,但是感觉这样的话,效率要低的多,因为好像要一直查库,每次都要循环一次,如果分类比较多的话,估计就用不了了。

============================================================================
package com.hmilyld.channel;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import com.hmilyld.study.DatabaseBean;

public class ChannelBean {
Connection conn ;
public ChannelBean(){
try {
this.conn=DatabaseBean.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
}

/*
* 查库,得到库中所有分类
*/
public Collection getChannel() throws SQLException{
Collection<Channel> rs = new ArrayList<Channel>();
Statement stm = conn.createStatement();
ResultSet rst = stm.executeQuery("select * from channel");
while (rst.next()){
Channel channel = new Channel();
channel.setChannelId(rst.getInt("id"));
channel.setChannelName(rst.getString("name"));
channel.setChannelParentId(rst.getInt("parentid"));
rs.add(channel);
}
conn.close();
return rs;
}

public static void main(String[] args) throws Exception{
ChannelBean channel = new ChannelBean();
Iterator it = channel.getChannel().iterator();
while(it.hasNext()){
Channel chan = (Channel)it.next();
if(chan.getChannelParentId()==0){
int i = chan.getChannelId();
System.out.println(chan.getChannelName()); //打印出最顶级分类
/*
* 打印出顶级分类下的分类,然后调用channelSort
*/
channel.channelSort(it,i);
}
}
}

public void channelSort(Iterator it,int id) throws Exception{
ChannelBean channel = new ChannelBean();
it = channel.getChannel().iterator();
while (it.hasNext()){
Channel chan = (Channel)it.next();
int channelChildId = chan.getChannelParentId();
int channelId = chan.getChannelId();
if(channelChildId==id){
System.out.println("--"+chan.getChannelName());
/*
* 一直循环调用
*/
channelSort(it,channelId);
}
}
}
}
============================================================================

这样似乎能一直无限分类下去,但是效率好像低的厉害,而且还有一个问题,
就是如果我想按照这种方式显示的话,好像不行。

根目录1
--子目录1
----子目录11
--子目录2

因为在后面的循环调用的时候,就都按照System.out.println("--"+chan.getChannelName());
这一句打印出来了,这应该怎么办?

希望高人指点一下,5.1什么都没弄,就整这个东西了,郁闷.- -#
hmilyld 2007-05-04
  • 打赏
  • 举报
回复
其实就是一个怎么实现无限分类,
不知道该怎么写这个东西了,
像一些文章系统中经常用的,对类别能进行无限分类那种。
林二棍子 2007-05-03
  • 打赏
  • 举报
回复
不是很明白楼主的意思。。。不过如果用ORACLE数据库的话,可以用下面的查询语句进行查询:

SELECT LEVEL, b.* FROM TABLE_NAME b CONNECT BY PRIOR b.id=b.childid START WITH b.childid=0

(有两个建议:第一,childid改名为parentid,因为你这个明显是父节点编号;第二,把childid作一个可以为空的FK,否则你将来会不好处理)

查询得结果:
level id name childid
1 1 根目录1 0
2 3 子目录1 1
2 4 子目录2 1
1 2 根目录2 0
2 5 子目录3 2
2 6 子目录4 2

这样查询出来的就是树形结构了。

如果需要在页面显示,可以用dtree.js控件显示成树形菜单

可以用我写的ctreetable.js控件显示成树形表格
或者用ctreeselector.js控件显示成树形下拉框
(下载地址:http://download.csdn.net/source/171981)

以上控件都不支持数据库动态加载,ctreetable和ctreeselector支持页面动态加载。

如果需要数据库动态加载,可以找找AJAX的树形控件。

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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