平衡二叉树(AVL树)

平衡二叉树的接口

package tree;

/**
 * 平衡二叉树的操作
 * 
 * @author liangguojun
 * 
 * @param <T>
 *            数据类型,该数据类型必须实现Comparable接口
 */
public interface SortAVLTree<T extends Comparable<T>> {
	public static final int ASC_VALUE = 1;
	public static final int DESC_VALUE = 0;

	/**
	 * 判断平衡二叉树是否为空
	 * 
	 * @return 平衡二叉树为空则返回true,否则返回false
	 */
	public boolean isEmpty();

	/**
	 * 求平衡二叉树的长度
	 * 
	 * @return 返回平衡二叉树的长度
	 */
	public int getLength();

	/**
	 * 插入数据,插入数据后自动调整平衡二叉树
	 * 
	 * @param data
	 *            数据元素
	 * @return 成功插入则返回true,否则返回false
	 */
	public boolean insert(T data);

	/**
	 * 删除数据元素节点
	 * 
	 * @param data
	 *            将要删除的数据元素节点
	 * @return 成功删除则返回true,否则返回false
	 */
	public boolean delete(T data);

	/**
	 * 根据传入的参数,按升序或者降序遍历平衡二叉树
	 * 
	 * @param VALUE
	 *            排序的控制参数
	 */
	public void view(int VALUE);

	/**
	 * 将数据元素move的数据改为data
	 * 
	 * @param data
	 *            替换的数据元素
	 * @param move
	 *            被替换的数据元素
	 * @return 成功替换则返回true,否则返回false
	 */
	public boolean update(T data, T move);

	/**
	 * 返回平衡二叉树的深度
	 * 
	 * @return 返回平衡二叉树的深度
	 */
	public int getDept();
}


平衡二叉树的节点类:

package tree;

/**
 * 平衡二叉树的节点类
 * 
 * @author liangguojun
 * 
 * @param <T>
 *            数据类型
 */
public class BirTreeNode<T> {
	private T data;
	private int bf;
	private BirTreeNode<T> lchild, rchild;

	public BirTreeNode(T data, int bf, BirTreeNode<T> lchild,
			BirTreeNode<T> rchild) {
		this.setData(data);
		this.setBf(bf);
		this.setLchild(lchild);
		this.setRchild(rchild);
	}

	public BirTreeNode(T data) {
		this(data, 0, null, null);
	}

	public BirTreeNode(T data, BirTreeNode<T> lchild, BirTreeNode<T> rchild) {
		this(data, 0, lchild, rchild);
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

	public int getBf() {
		return bf;
	}

	public void setBf(int bf) {
		this.bf = bf;
	}

	public BirTreeNode<T> getLchild() {
		return lchild;
	}

	public void setLchild(BirTreeNode<T> lchild) {
		this.lchild = lchild;
	}

	public BirTreeNode<T> getRchild() {
		return rchild;
	}

	public void setRchild(BirTreeNode<T> rchild) {
		this.rchild = rchild;
	}

	public String toString() {
		return data.toString();
	}
}

平衡二叉树的实现,参考《大话数据结构》的实现方法


package tree;
/**
 * 平衡二叉树的实现,参考《大话数据结构》的实现方法
 * @author liangguojun
 *
 * @param <T>
 */
public class AVLSortTree<T extends Comparable<T>> implements SortAVLTree<T> {

	// 用于控制插入一个节点后判断树是否长高了。
	private boolean taller = false;
	// 用于控制删除数据元素是树是否变矮了。
	private boolean shorter = false;
	// 根节点
	private BirTreeNode<T> root;
	// 左高
	public static final int LH = 1;
	// 等高
	public static final int EH = 0;
	// 右高
	public static final int RH = -1;

	public AVLSortTree() {
		root = null;
	}

	// 返回根节点
	public BirTreeNode<T> getRoot() {
		return root;
	}

	@Override
	public boolean isEmpty() {
		if (root == null) {
			return true;
		}
		return false;
	}

	/**
	 * 求子树cur的长度
	 * 
	 * @param cur
	 *            子树的根结点cur
	 * @return 返回子树的长度
	 */
	private int getLength(BirTreeNode<T> cur) {
		if (cur != null) {
			int lc = 0;
			int rc = 0;
			if (cur.getLchild() != null)
				lc = getLength(cur.getLchild()) + 1;
			if (cur.getRchild() != null)
				rc = getLength(cur.getRchild()) + 1;
			return lc + rc;
		}
		return 0;
	}

	@Override
	public int getLength() {
		if (root != null)
			return getLength(root) + 1;
		return 0;
	}

	/**
	 * 右旋转的方法,当子树右旋转时,双亲不为空,则应该修改双亲的节点
	 * 
	 * @param cur
	 *            需要旋转的子树根节点
	 * @param parent
	 *            子树的双亲节点
	 */
	private void rightRotate(BirTreeNode<T> cur, BirTreeNode<T> parent) {
		if (cur != null && cur.getLchild() != null) {
			// 旋转操作
			BirTreeNode<T> L = cur.getLchild();
			cur.setLchild(L.getRchild());
			L.setRchild(cur);
			// 假如是根节点的话,则修改根节点
			if (parent == null) {

				root = L;

			} else {

				// 假如cur的双亲parent的左孩子是cur,则修改左孩子,否则修改右孩子
				if (parent != null && parent.getLchild() == cur) {
					parent.setLchild(L);
				} else if (parent != null && parent.getRchild() == cur) {
					parent.setRchild(L);
				}
			}
		}
	}

	/**
	 * 左旋转的方法
	 * 
	 * @param cur
	 *            需要左旋转的子树的根节点
	 * @param parent
	 *            需要旋转子树的双亲节点
	 */
	private void leftRotate(BirTreeNode<T> cur, BirTreeNode<T> parent) {
		if (cur != null && cur.getRchild() != null) {
			BirTreeNode<T> R = cur.getRchild();
			cur.setRchild(R.getLchild());
			R.setLchild(cur);
			// 假如是根节点的话,则修改根节点
			if (parent == null) {
				root = R;
			}
			if (parent != null && parent.getLchild() == cur) {
				parent.setLchild(R);
			} else if (parent != null && parent.getRchild() == cur) {
				parent.setRchild(R);
			}

		}
	}

	/**
	 * 对cur为根节点的二叉树做左旋转处理,方法结束后,根节点改变,如果cur右双亲节点,则应该修改双亲节点的孩子节点
	 * 
	 * @param cur
	 *            二叉树的根节点
	 * @param parent
	 *            cur二叉树的双亲节点
	 */
	private void leftBalance(BirTreeNode<T> cur, BirTreeNode<T> parent) {
		if (cur.getLchild() != null) {
			BirTreeNode<T> L = cur.getLchild();
			BirTreeNode<T> Lr;
			switch (L.getBf()) {
			case LH: // 根节点左边高,左子树也是左边高,所以直接一次右旋转即可
				cur.setBf(EH);
				L.setBf(EH);
				rightRotate(cur, parent);
				break;

			case RH: // 根节点左边高,而左子树是右边树高,所以要双旋转,使要旋转的树的符号一样
						// 先对左子树左旋转,使左子树变成左边高 ,才能进行右旋转
				Lr = L.getRchild();
				// 修改平衡标志
				switch (Lr.getBf()) {
				case LH:
					cur.setBf(RH);
					L.setBf(EH);
					break;
				case EH:
					cur.setBf(EH);
					L.setBf(EH);
					break;
				case RH:
					cur.setBf(EH);
					L.setBf(LH);
					break;
				}
				Lr.setBf(EH);
				// 先对最小不平衡树左旋
				leftRotate(L, cur);
				// 对整棵树进行右旋
				rightRotate(cur, parent);
			}
		}
	}

	/**
	 * 对cur为根节点的二叉树做右旋转处理,方法结束后,根节点改变,如果cur右双亲节点,则应该修改双亲节点的孩子节点
	 * 
	 * @param cur
	 *            需要进行右平衡处理的子树的根节点
	 * @param parent
	 *            cur的双亲节点
	 */
	private void rightBalance(BirTreeNode<T> cur, BirTreeNode<T> parent) {
		if (cur.getRchild() != null) {
			BirTreeNode<T> R = cur.getRchild();
			BirTreeNode<T> Rl;
			switch (R.getBf()) {
			// 旋转时的子树根节点右边高
			case RH:
				cur.setBf(EH);
				R.setBf(EH);
				leftRotate(cur, parent);
				break;
			// 旋转时的子树的根节点左边高,跟根节点的符号不一样,要进行双旋转处理
			case LH:
				Rl = R.getLchild();
				switch (Rl.getBf()) {
				case LH:
					R.setBf(RH);
					cur.setBf(EH);
					break;
				case EH:
					R.setBf(EH);
					cur.setBf(EH);
					break;
				case RH:
					cur.setBf(LH);
					R.setBf(EH);
					break;
				}
				Rl.setBf(EH);
				rightRotate(R, cur);
				leftRotate(cur, parent);

			}
		}
	}

	/**
	 * 插入节点的方法
	 * 
	 * @param cur
	 *            被插入的节点
	 * @param parent
	 *            插入节点的双亲
	 * @param data
	 *            插入的数据元素
	 * @return 成功插入则返回true,否则返回false
	 */
	private boolean insert(BirTreeNode<T> cur, BirTreeNode<T> parent, T data) {

		if (data != null) {
			if (cur == null) {
				cur = new BirTreeNode<T>(data);
				// 插入节点作为双亲节点的左孩子还是右孩子
				if (parent.getData().compareTo(cur.getData()) > 0) {
					parent.setLchild(cur);
				}
				if (parent.getData().compareTo(cur.getData()) < 0) {
					parent.setRchild(cur);
				}
				taller = true;
			} else {
				if (data.compareTo(cur.getData()) == 0) {
					taller = false;
					return false;
				}
				if (data.compareTo(cur.getData()) < 0) {
					// 递归调用插入函数,插入到左子树中
					if (!insert(cur.getLchild(), cur, data)) {
						return false;
					}
					// 若插入成功插入左子树,且左子树长高,进行平衡度检查
					if (taller) {
						switch (cur.getBf()) {
						// 原本左子树比右子树高,需要做左平衡处理
						case LH:
							leftBalance(cur, parent);
							taller = false;
							break;
						// 原本左子树和右子树等高,现在因为左子树增高而树增高
						case EH:
							cur.setBf(LH);
							taller = true;
							break;
						// 原本右子树比左子树高,现在左右子树等高
						case RH:
							cur.setBf(EH);
							taller = false;
							break;
						}

					}
				} else {
					if (!insert(cur.getRchild(), cur, data))
						return false;
					// 假如taller为ture,则成功插入右子树,且树已长高,进行平衡度检查
					if (taller) {

						switch (cur.getBf()) {
						case LH: // 原本左子树比右子树高,现在左右子树等高
							cur.setBf(EH);
							taller = false;
							break;
						case EH: // 原本左右子树等高,现因为右子树增高而树增高
							cur.setBf(RH);
							taller = true;
							break;
						case RH: // 原本右子树比左子树高,需要做右平衡处理
							rightBalance(cur, parent);
							taller = false;
							break;
						}
					}
				}

			}
			return true;
		}
		return false;
	}

	@Override
	public boolean insert(T data) {
		if (root == null) {
			root = new BirTreeNode<T>(data);
			this.taller = false;
			return true;
		}

		boolean tmp = insert(root, null, data);
		taller = false;
		return tmp;
	}

	/**
	 * 删除节点时左平衡旋转处理
	 * 
	 * @param cur
	 *            删除的树的根节点
	 * @param parent
	 *            子树cur的双亲节点
	 */
	private void leftBalance_div(BirTreeNode<T> cur, BirTreeNode<T> parent) {
		BirTreeNode<T> p1, p2;
		switch (cur.getBf()) {
		case LH:
			cur.setBf(EH);
			shorter = true;
			break;
		case EH:
			cur.setBf(RH);
			shorter = false;
			break;
		case RH:
			// 
			//
			p1 = cur.getRchild();
			switch (p1.getBf()) {
			case EH:
				p1.setBf(LH);
				cur.setBf(RH);
				shorter = false;
				leftRotate(cur, parent);
				break;
			case RH:

				p1.setBf(EH);
				cur.setBf(EH);
				shorter = true;
				rightRotate(cur, parent);
				break;
			case LH:
				// 
				p2 = p1.getLchild();
				if (p2.getBf() == EH) {
					cur.setBf(EH);
					p1.setBf(EH);
				} else if (p2.getBf() == RH) {
					cur.setBf(LH);
					p1.setBf(EH);
				} else {
					cur.setBf(EH);
					p1.setBf(-1);
				}
				p2.setBf(EH);
				rightRotate(p1, cur);
				shorter = true;
				// 这里要旋转吗?
				leftRotate(cur, parent);
			}
		}
	}

	/**
	 * 删除节点时右平衡旋转处理
	 * 
	 * @param cur
	 *            要旋转的子树的根节点
	 * @param parent
	 *            子树的根节点的双亲节点
	 */
	private void rightBalance_div(BirTreeNode<T> cur, BirTreeNode<T> parent) {
		BirTreeNode<T> p1, p2;
		switch (cur.getBf()) {
		case RH:
			cur.setBf(EH);
			shorter = true;
			break;
		case EH:
			cur.setBf(LH);
			shorter = false;
			break;
		case LH:

			p1 = cur.getLchild();
			switch (p1.getBf()) {
			case EH:

				// 这里需要旋转
				p1.setBf(RH);
				cur.setBf(LH);
				rightRotate(cur, parent);
				shorter = false;
				break;
			case LH:

				p1.setBf(EH);
				cur.setBf(EH);
				rightRotate(cur, parent);

				shorter = true;
				break;
			case RH:
				// 
				p2 = p1.getRchild();
				if (p2.getBf() == EH) {
					cur.setBf(EH);
					p1.setBf(EH);
				} else if (p2.getBf() == LH) {
					cur.setBf(RH);
					p1.setBf(EH);
				} else {
					cur.setBf(EH);
					p1.setBf(RH);
				}
				p2.setBf(EH);
				leftRotate(p1, cur);
				shorter = true;
				// 这里需要右旋吗?
				rightRotate(cur, parent);
			}
		}
	}

	/**
	 * 删除节点cur,找到替代的节点r
	 * 
	 * @param cur
	 *            被删除的节点
	 * @param childParent
	 *            替代节点的双亲节点
	 * @param r
	 *            替代节点
	 * @param parent
	 *            被删除节点的双亲节点
	 */
	private void delete(BirTreeNode<T> cur, BirTreeNode<T> childParent,
			BirTreeNode<T> r, BirTreeNode<T> parent) {
		// 寻找替代节点的方法,替代的节点是被删除节点的左子树的最右的节点
		//
		if (r.getRchild() == null) {
			if (parent != null) {

				if (parent.getLchild() == cur) {

					// 替代被删除的节点
					parent.setLchild(r);
					// 被替代的节点的双亲节点修改孩子节点
					if (childParent.getLchild() == r) {
						childParent.setLchild(r.getLchild());
					} else if (childParent.getRchild() == r) {
						childParent.setRchild(r.getLchild());
					}
					// 替代的节点接替被删除的左孩子和右孩子
					r.setLchild(cur.getLchild());
					r.setRchild(cur.getRchild());
				} else if (parent.getRchild() == cur) {
					// 替代被删除的节点
					parent.setRchild(r);
					// 被替代的节点的双亲节点修改孩子节点
					if (childParent.getLchild() == r) {
						childParent.setLchild(r.getLchild());
					} else if (childParent.getRchild() == r) {
						childParent.setRchild(r.getLchild());
					}
					// 替代的节点接替被删除的左孩子和右孩子
					r.setLchild(cur.getLchild());
					r.setRchild(cur.getRchild());
				}
			} else {

				root = r;

				if (childParent.getLchild() == r) {

					childParent.setLchild(r.getLchild());
				} else if (childParent.getRchild() == r) {

					childParent.setRchild(r.getLchild());
				}
				// 到这里为止,已经删除成功,接下来就要进行左子树的平衡处理了
				//
				root.setLchild(cur.getLchild());
				root.setRchild(cur.getRchild());
			}
			shorter = true;
		} else if (r.getRchild() != null) {
			// 假如左子树的右子树还没到最后的右子树,则继续递归
			delete(cur, r, r.getRchild(), parent);
			if (shorter) {
				// 
				//
				rightBalance_div(r, root);
			}
		}
	}

	/**
	 * 删除平衡二叉树的数据元素data
	 * 
	 * @param data
	 *            要删除的数据元素
	 * @param cur
	 *            删除的子树的根节点
	 * @param parent
	 *            cur的双亲节点
	 * @return 成功删除则返回true,否则返回false
	 */
	private boolean delete(T data, BirTreeNode<T> cur, BirTreeNode<T> parent) {
		if (cur != null) {
			// 假如删除的数据元素比当前节点小
			if (data.compareTo(cur.getData()) < 0) {
				delete(data, cur.getLchild(), cur);
				if (shorter) {
					// 
					//
					leftBalance_div(cur, parent);
				}
				// 设置树变矮标志
				// shorter = false;
				return true;
			} else if (data.compareTo(cur.getData()) > 0) {
				// 假如删除的数据元素比当前数据元素大

				delete(data, cur.getRchild(), cur);
				if (shorter) {
					rightBalance_div(cur, parent);
				}
				// 设置树变矮的标志,这里不需要
				// shorter = false;
				return true;
			} else {

				// 假如当前节点的右子树为空, 删除当前节点,重接左子树
				if (cur.getRchild() == null) {
					if (parent.getLchild() == cur) {
						parent.setLchild(cur.getLchild());
					} else if (parent.getRchild() == cur) {
						parent.setRchild(cur.getLchild());
					}
					shorter = true;
				} else if (cur.getLchild() == null) {
					// 假如当前节点的左子树为空,删除当前节点,重接右子树
					if (parent.getLchild() == cur) {
						parent.setLchild(cur.getRchild());
					} else if (parent.getRchild() == cur) {
						parent.setRchild(cur.getRchild());
					}

					shorter = true;
				} else {

					// 当左右子树都不为空的时候,寻找替代节点
					// 
					//
					delete(cur, cur, cur.getLchild(), parent);

					if (shorter) {
						leftBalance_div(cur, parent);
					}
				}
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean delete(T data) {
		if (data != null) {

			return delete(data, root, null);
		}
		return false;
	}

	/**
	 * 升序遍历平衡二叉树
	 * 
	 * @param cur
	 *            需要遍历的树的根节点
	 */
	private void viewASC(BirTreeNode<T> cur) {
		if (cur != null) {
			viewASC(cur.getLchild());
			System.out.print(cur.getData() + " ");
			System.out.println("当前标志值为:" + cur.getBf() + "他的左孩子为:"
					+ cur.getLchild() + "右孩子为:" + cur.getRchild());
			viewASC(cur.getRchild());
		}
	}

	/**
	 * 降序遍历平衡二叉树
	 * 
	 * @param cur
	 *            需要遍历的树的根节点
	 */
	private void viewDESC(BirTreeNode<T> cur) {
		if (cur != null) {
			viewDESC(cur.getRchild());
			System.out.print(cur.getData() + " ");
			viewDESC(cur.getLchild());
		}

	}

	@Override
	public void view(int VALUE) {
		switch (VALUE) {
		case ASC_VALUE:
			viewASC(root);
			System.out.println();
			break;
		case DESC_VALUE:
			viewDESC(root);
			System.out.println();
			break;
		}

	}

	@Override
	public boolean update(T data, T move) {
		if (data != null && move != null) {
			this.delete(move);
			return this.insert(data);
		}
		return false;

	}

	/**
	 * 求平衡二叉树的深度
	 * 
	 * @param cur
	 *            子树的根节点
	 * @return 返回平衡二叉树的深度
	 */
	private int getDept(BirTreeNode<T> cur) {
		if (cur != null) {
			int lc = getDept(cur.getLchild()) + 1;
			int rc = getDept(cur.getRchild()) + 1;
			return lc > rc ? lc : rc;
		}
		return 0;
	}

	@Override
	public int getDept() {
		return getDept(root);
	}

	/**
	 * 清空整棵树
	 */
	public void clear() {
		root = null;
	}

	/**
	 * 先序遍历平衡二叉树,做测试用
	 * 
	 * @param cur
	 *            子树的根节点
	 */
	private void view(BirTreeNode<T> cur) {
		if (cur != null) {

			System.out.print(cur.getData() + " ");

			view(cur.getLchild());
			view(cur.getRchild());
		}
	}

	/**
	 * 先序遍历平衡二叉树,做测试用。
	 */
	public void view() {
		view(root);
		System.out.println();
	}

	// 测试
	public static void main(String[] args) {
		String[] a = { "J", "F", "I", "H", "C", "G", "B", "E", "D", "A" };
		AVLSortTree<String> test = new AVLSortTree<>();
		for (int i = 0; i < a.length; i++) {
			test.insert(a[i]);
		}
		// // System.out.println(test.insert("H"));
		// test.view(ASC_VALUE);
		// System.out.println("排序二叉树的深度 " + test.getDept());
		// System.out.println("长度?:" + test.getLength());
		// // System.out.println("是否为空:" + test.isEmpty());
		// test.view();

		System.out.println("初次尝试删除:::" + test.delete("A"));
		// System.out.println("根节点的标志值:" + test.getRoot().getBf());

		// test.delete("J");
		// test.delete("C");
		// test.delete("D");
		// test.delete("G");
		test.insert("K");
		System.out.println("初次尝试删除:::" + test.delete("B"));
		test.insert("L");
		test.insert("M");
		test.insert("N");
		test.insert("O");
		test.insert("P");
		test.insert("Q");
		test.insert("R");
		test.insert("S");
		test.insert("T");
		test.insert("U");
		test.insert("V");
		test.insert("W");
		test.insert("X");
		// test.insert("A");
		System.out.println("排序二叉树的深度 " + test.getDept());
		System.out.println("根节点的数据元素为:" + test.getRoot().getData());
		test.view();
		test.view(ASC_VALUE);
	}
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值