简单二叉树的基本功能(二)

删除节点是二叉树中最复杂的一部分,所以放在此处单独说明。

基本思路:

1. 首先,在删除之前我们需要查找到需要删除的节点。这一点可以借鉴find()方法。

2. 找到之后,我们需要了解该如何删除此节点。首先我们知道,要删除的节点可能出现的情况有三种:

     ①该节点是叶子节点,即没有子节点。

     那么要删除它,自然可以直接删除啦,只需要改变父节点的引用值就行,即将指向该节点的引用设置为null

    ②该节点有一个子节点

            那么要改变父节点的引用,将父节点的引用设置成要删除节点的子节点

    ③该节点有两个子节点

            这种情况要考虑的情况最为复杂。若要删除此类节点,则需要使用它的中序后继来替代该节点。

    其中,中序后继指的是:比该节点大,但是是数值最为接近该节点的节点,这个节点即为中序后继。


下面给出删除节点的方法以及寻找中序后继的方法:

/**
	 *  删除节点
	 * @param data
	 */
	public void delete(int data) {
		
		//引用当前节点,从根节点开始
		Node current = root;
		
		//引用当前节点的父节点
		Node parent = root;
		
		//是否为左孩子
		boolean isLeftChild = true;
		//先找到该节点
		while(current.data != data) {
			parent = current;
			//进行比较,比较查找值和当前节点的大小
			if(current.data>data) {
				current = parent.leftChild;
				isLeftChild = true;
			} else {
				current = parent.rightChild;
				isLeftChild = false;
			}
			//若树中无要删除的节点
			if(current == null) {
				System.out.println("对不起,未查找到要删除的节点!");
				return;
			}
		}
		
		//删除节点
		//1.若该节点是叶子节点,即没有孩子
		if(current.leftChild == null && current.rightChild == null) {
			//注意!记得考虑要删除节点为root的情况
			if(current == this.root) {
				this.root = null;
				System.out.println("要删除的数据: " + current.data + ", " + current.sdata);
				System.out.println("删除成功!");
				return;
			}
			//如果要删除的节点是父节点的左孩子
			if(isLeftChild)
				parent.leftChild = null;
			else
				parent.rightChild = null;
			//如果要删除的节点是父节点的左孩子
			System.out.println("要删除的数据: " + current.data + ", " + current.sdata);
			System.out.println("删除成功!");
			return;
		} else if(current.rightChild == null) {// 若要删除的节点只要一个左孩子
			//注意!记得考虑要删除节点为root的情况
			if(current == this.root) {
				this.root = current.leftChild;
				System.out.println("要删除的数据: " + current.data + ", " + current.sdata);
				System.out.println("删除成功!");
				return;
			}
			if(isLeftChild)
				parent.leftChild = current.leftChild;
			else
				parent.rightChild = current.leftChild;
			System.out.println("要删除的数据: " + current.data + ", " + current.sdata);
			System.out.println("删除成功!");
		} else if(current.leftChild == null) {//若要删除的节点只有一个右孩子
			//注意!记得考虑要删除节点为root的情况
			if(current == this.root) {
				this.root = current.rightChild;
				System.out.println("要删除的数据: " + current.data + ", " + current.sdata);
				System.out.println("删除成功!");
				return;
			}
			if(isLeftChild)
				parent.leftChild = current.rightChild;
			else
				parent.rightChild = current.rightChild;
			System.out.println("要删除的数据: " + current.data + ", " + current.sdata);
			System.out.println("删除成功!");
		} else { //最后一种情况,即要删除节点有两个孩子
			Node successor = getSuccessor(current);
			if(current == root) {
				this.root = successor;
			} else if(isLeftChild) {
				// 若要删除节点是一个左子节点
				parent.leftChild = successor;
			} else {
				parent.rightChild = successor;
			}
			successor.leftChild = current.leftChild;
			System.out.println("要删除的数据: " + current.data + ", " + current.sdata);
			System.out.println("删除成功");
		}
	}
	
	/**
	 * 用来寻找中序后继节点
	 * @param delNode
	 * @return 返回中序后继节点
	 */
	public Node getSuccessor(Node delNode) {
		//先建立一个引用
		Node successor = delNode;
		//建立一个父节点
		Node successorParent = delNode;
		//这里因为是循环中序后继,所以是从要删除节点的右子树开始寻找
		Node current = delNode.rightChild;
		//假设要删除节点为P,P的右孩子为P1,则中序后继只可能存在于P1的左子树上或者是P1本身
		while(current != null) {
			successorParent = successor;
			successor = current;
			current = current.leftChild;
		}
		if(successor != delNode.rightChild) {
			successorParent.leftChild = successor.rightChild;
			successor.rightChild = delNode.rightChild;
		}
		return successor;
	}


猜你喜欢

转载自blog.csdn.net/hjl_heart/article/details/80153043