JAVA中如何删除树中所选的节点?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA中如何删除树中所选的节点?相关的知识,希望对你有一定的参考价值。

已有树状结构,欲删除鼠标所选的节点,请教代码.谢谢.
我用的是JBuilder,然后用JTree jtree1=new JTree()建了一个系统的示例树。
现在想删除里面的某个子节点.
如何编写此代码?

//获得商品分类树形结构
private JTree getTree()
if(tree ==null)

tree = new JTree(getTreeModel());
tree.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
// tree = new JTable(getModel());
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
// 节点选择事件
tree.addTreeSelectionListener(new TreeSelectionListener()

public void valueChanged(TreeSelectionEvent e)
treeSelection();


);

tree.addMouseListener(new MouseAdapter()
public void mousePressed(MouseEvent e)
if(e.getButton()==MouseEvent.BUTTON3)

int selRow = tree.getRowForLocation(e.getX(), e.getY());
tree.setSelectionRow(selRow);

TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());

if(selRow != -1)
if(e.getClickCount() == 1)
// myRightClick(selRow, selPath);
selectedNode = (DefaultMutableTreeNode) selPath.getLastPathComponent();
showPopMenu(selRow,selPath,e.getX(),e.getY());







);


return tree;

/**
* 获得当前选择的商品对象
* @return
*
*/
private Goods getSelectedGoods()
int row = table.getSelectedRow();
if(row!=-1)

String code = (String)getModel().getValueAt(row,0);
Goods g= gHandle.getGoodsByCode(code);

return g;

return null;


/**
* 树形结构上显示右键菜单
* @param selRow
* @param selPath
*
*/
private void showPopMenu(int selRow, TreePath path,int x,int y)
// tree.add(getPopMenu());
if (path == null)
return;
//点的是根结点
if(selectedNode.isRoot())

JPopupMenu pop = getPopMenu(1,path,selRow);
// System.out.println(selRow);
this.getContentPane().add(pop);
pop.show(tree,x,y);

//叶结点
if(selectedNode.isLeaf())

JPopupMenu pop = getPopMenu(0,path,selRow);
this.getContentPane().add(pop);
pop.show(tree,x,y);



/**
* 创建右键菜单
* @param action
* @return
*
*/
private JPopupMenu getPopMenu(int action,final TreePath path,final int selRow)
if(pop==null)

pop = new JPopupMenu();

//新建类别事件处理
addItem.addActionListener(new ActionListener()

public void actionPerformed(ActionEvent e)
String value = JOptionPane.showInputDialog("请输入新类别的名称:");
if(value==null||value.trim().length()==0)
return;
GoodsCategoryHandle gcHandle = new GoodsCategoryHandle();
if(gcHandle.isExsited(value))

JOptionPane.showMessageDialog(null, "该类别名称已经存在!", "提示", JOptionPane.ERROR_MESSAGE);
return ;


DefaultMutableTreeNode newNode =new DefaultMutableTreeNode(value);
treeModel.insertNodeInto(newNode,(MutableTreeNode)treeModel.getRoot(),selRow-1);
GoodsCategory gc = new GoodsCategory();
gc.setCategoryName(value);
//更新到数据库中
gcHandle.addCategory(gc);



);
//重命名类别名称事件处理
renameItem.addActionListener(new ActionListener()

public void actionPerformed(ActionEvent e)

String value = JOptionPane.showInputDialog(null,"请输入新类别的名称:",selectedNode.toString());

if(value==null||value.trim().length()==0)
return;
GoodsCategoryHandle gcHandle = new GoodsCategoryHandle();
if(gcHandle.isExsited(value))

JOptionPane.showMessageDialog(null, "该类别名称已经存在!", "提示", JOptionPane.ERROR_MESSAGE);
return ;


GoodsCategory gc =gcHandle.getCategory(selectedNode.toString());
gc.setCategoryName(value);
//更新到数据库中
gcHandle.modifyCategory(gc);
selectedNode.setUserObject(value);
tree.setModel(getTreeModel());



);
//移除结点事件处理
delItem.addActionListener(new ActionListener()

public void actionPerformed(ActionEvent e)

int i =JOptionPane.showConfirmDialog(null,
"慎重!删除类别后,该类别下的所有商品将全部被删除,确认后继续", "提示", JOptionPane.YES_NO_OPTION);
if(i==JOptionPane.YES_OPTION)


GoodsCategoryHandle gcHandle = new GoodsCategoryHandle();
GoodsHandle gHandle = new GoodsHandle();

int id = (gcHandle.getCategory(selectedNode.toString().trim())).getCategoryId();
ArrayList al = gHandle.getGoodsByCategory(id);

boolean b_bak = false;
//对删除商品的备分
try
FileWriter out = new FileWriter("/"+CommonUtil.getTime()+"商品删除bak.db",true);
out.write("商品名称"+" "+"商品分类"+" "+
"商品别名"+" "+"商品单位"+" "+
"商品厂商"+" "+"商品库存上限"+" "+
"商品库存下限"+" "+
"商品库存下限"+" "+
"商品参考售价"+" "+
"商品实际库存");
out.write('\n');
for(int j=0;j<al.size();j++)

Goods g = (Goods)al.get(j);
out.write(g.toString());
out.write('\n');

out.close();
b_bak=true;
catch (IOException e1)
e1.printStackTrace();
b_bak = false;


gcHandle.setCommit(false);
boolean g_del=gHandle.deleteByCategoryId(id);
boolean gc_del=gcHandle.deleteById(id);
//只有类别删除成功,该类别下的商品删除成功,并且备分成功后才提交删除
if(g_del&&gc_del&&b_bak)
gcHandle.commit();
else

// System.out.println("fail");
gcHandle.rollBack();
JOptionPane.showMessageDialog(null, "删除失败,可能是因为该类别下的商品存在销售记录,不能被删除!", "提示", JOptionPane.ERROR_MESSAGE);

tree.setModel(getTreeModel());
tree.setSelectionRow(0);


else
return;



);
pop.add(addItem);
pop.add(delItem);
pop.add(renameItem);

if(action ==1)

delItem.setEnabled(false);
renameItem.setEnabled(false);

if(action ==0)

delItem.setEnabled(true);
renameItem.setEnabled(true);

return pop;

/**
* 用户在商品分类树上的事件处理
*
*
*/
private void treeSelection()
TreePath path = tree.getSelectionPath();
if (path == null)
return;
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
.getLastPathComponent();

selectedCategory = cHandle.getCategory(node.toString());
// 若选中的是根节点
if (node.isRoot())

showAllGoods();

if(node.isLeaf())
model.setRowCount(0);
ArrayList al = gHandle.getGoodsByCategoryName(node
.toString());
for (int i = 0; i < al.size(); i++)
Goods g = (Goods) al.get(i);
model.addRow(getRow(g));





public GoodsCategory getCategory()
return this.selectedCategory;


/**
* 生产树形列表的数据模型
*
* @return
*
*/
private TreeModel getTreeModel()
DefaultMutableTreeNode root = new DefaultMutableTreeNode(
PropertiesUtil.getString("categoryTree.all"));
ArrayList categoryList = cHandle.getAllCategory();
// 添加子节点
for (int i = 0; i < categoryList.size(); i++)
GoodsCategory gc = (GoodsCategory) categoryList.get(i);
String name = gc.getCategoryName();
DefaultMutableTreeNode node = new DefaultMutableTreeNode(name);
root.add(node);

// 生产treeModel
treeModel = new DefaultTreeModel(root);

return treeModel;
参考技术A javax.swing.tree.DefaultTreeModel.removeNodeFromParent(MutableTreeNode node)
用于从树模型中删除节点。

欲删除鼠标所选的节点
DefaultMutableTreeNode selectedNode =
    (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if (selectedNode != null && selectedNode.getParent() != null)
    model.removeNodeFromParent(selectedNode);


建议还是找本书看看吧,JTree用了MVC模式,还是从基础看起比较好,推荐CoreJava这本书的第二卷,里面有详细介绍。
参考技术B 在这里写不太方便,请发消息告知我邮箱,我可以做个示例给你传过去,OK?

LeetCode Java刷题笔记— 450. 删除二叉搜索树中的节点

450. 删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

中等难度。有两种方式一种是递归,另一种是非递归。

我们首先要找到被值相同的节点A:

  1. 如果该节点的一个子树为空,那么用另一个子树的根节点代替当前节点的位置即可。

  2. 如果该节点的两个子树都为空,那么删除该节点即可,这就是第一种情况的特例。

  3. 如果该节点的左右子树都不为null,那么找到左子树的最大节点或者右子树的最小节点B,此时剩下的步骤有两个思路

    1. 第一种是方法是将A的左子树赋值给B的左子树(如果B是右子树的最小节点),或者将A的右子树赋值给B的右子树(如果B是左子树的最大节点)。
    2. 另一种方法是将找到的节点B的值赋给节点A,然后删除找到的节点B,这样的好处是不会增加树的层级。

迭代算法:

public TreeNode deleteNode(TreeNode root, int key) 

    if (root == null) 
        return null;
    
    //node 值相等的节点  pre 被删除节点的前驱节点  removeNode 真正被删除的节点
    TreeNode node = root, pre = null, removeNode = root;
    while (node != null) 
        //找到了key相等的节点
        if (node.val == key) 
            //开始查找真正需要删除的节点
            removeNode = node;
            //查找左子树的最大节点
            if (removeNode.left != null && removeNode.right != null) 
                pre = removeNode;
                removeNode = removeNode.left;
                while (removeNode.right != null) 
                    pre = removeNode;
                    removeNode = removeNode.right;
                
            
            break;
        
        pre = node;
        node = node.val > key ? node.left : node.right;
    
    //如果没找到,那么返回root
    if (node == null) 
        return root;
    
    //交换值,然后删除真正需要被删除的节点
    node.val = removeNode.val;
    if (pre != null) 
        if (removeNode == pre.left) 
            pre.left = removeNode.left != null ? removeNode.left : removeNode.right;
        
        if (removeNode == pre.right) 
            pre.right = removeNode.left != null ? removeNode.left : removeNode.right;
        
        return root;
    
    root = removeNode.left != null ? removeNode.left : removeNode.right != null ? removeNode.right : null;
    return root;

递归算法,更好理解,就是一个dfs递归遍历:

public TreeNode deleteNode(TreeNode root, int key) 
    if (root == null) 
        return null;
    
    if (root.val > key) 
        root.left = deleteNode(root.left, key);
     else if (root.val < key) 
        root.right = deleteNode(root.right, key);
     else 
        //1 2 该节点的至少一个子树为空,返回另一个子树
        if (root.left == null || root.right == null)
            return root.left != null ? root.left : root.right != null ? root.right : null;
        else 
            //3 该节点的左右子树都不为null

            //查找右子树的最小节点p
            TreeNode p = root.right;
            while (p.left != null) 
                p = p.left;
            
            //root的左子树赋值给p的左子树
            p.left = root.left;
            root = root.right;
            return root;
        
    
    return root;

以上是关于JAVA中如何删除树中所选的节点?的主要内容,如果未能解决你的问题,请参考以下文章

如何删除树中的节点?

Java 求解删除二叉搜索树中的节点

复制并删除所选的列表框项目

二叉搜索树中删除的时间复杂度

LeetCode Java刷题笔记— 450. 删除二叉搜索树中的节点

红黑树之删除节点