欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《算法导论》第12章二叉搜索树Java实现

程序员文章站 2022-05-07 08:37:33
...

1.二叉树中的结点类Node,保存了树中一个结点的值,和它的父亲结点,左孩子结点与右孩子结点

//二叉树中的结点类,保存了树中一个结点的值,和它的父亲结点,左孩子结点与右孩子结点
public class Node {
	int key;//结点的值
	Node p;//父亲结点
	Node left;//左孩子结点
	Node right;//右孩子结点
	
	//添加一个构造方法,方便封装数值
	public Node(int key) {
		this.key=key;
	}
}

2.二叉搜索树类Binary_Search_Tree,按次序实现了书中正文的方法:

INORDER-TREE-WALK:中序遍历树的方法
PREDECESSOR-TREE-WALK:前序遍历树的方法
TREE-SEARCH:查询二叉树的某个结点递归版
ITERATIVE-TREE-SEARCH:查询二叉树的某个结点迭代版
TREE-MINIMUM:返回树中最小值结点
TREE-MAXIMUM:返回树中的最大值结点
TREE-SUCCESSOR:寻找某个结点在中序遍历序列的后继
TREE-PREDECESSOR:寻找某个结点在中序遍历序列的前驱
TREE-INSERT:树中插入某个结点
TRANSPLANT:搜索二叉树的更换结点操作,将树中以u为根结点的子树更换为新结点以v为根的子树
TREE-DELETE:删除树中某个结点

//搜索二叉树类
public class Binary_Search_Tree {
	private Node root;//树的根节点
	
	public Binary_Search_Tree() {
		this.root =null;
	}

	//中序遍历整个二叉树
	public void Inorder_Tree_Walk() {
		this.Inorder_Tree_Walk(this.root);
		System.out.println();
	}
	//中序遍历二叉树的某个结点
	private void Inorder_Tree_Walk(Node x) {
		if(x!=null) {
			Inorder_Tree_Walk(x.left);
			System.out.print(x.key+" ");
			Inorder_Tree_Walk(x.right);
		}
	}
	
	//前序遍历整个二叉树
	public void Preorder_Tree_Walk() {
		this.Preorder_Tree_Walk(this.root);
		System.out.println();
	}
	//前序遍历二叉树的某个结点
	private void Preorder_Tree_Walk(Node x) {
		if(x!=null) {
			System.out.print(x.key+" ");
			Preorder_Tree_Walk(x.left);
			Preorder_Tree_Walk(x.right);
		}
	}
	
	//在二叉树中查询某个值,返回包含该值的Node结点,递归版本
	public Node Tree_Search(int k) {
		return Tree_Search(root, k);//传入root结点,从root结点往下搜索
	}
	//二叉树从某个结点x向下搜索k值的方法,返回包含k值的结点,递归版本
	private Node Tree_Search(Node x,int k) {
		if(x==null||k==x.key) {
			return x;
		}
		if(k<x.key) {
			return Tree_Search(x.left, k);
		}else {
			return Tree_Search(x.right, k);
		}
	}

	//在二叉树中查询某个值,返回包含该值的Node结点,递归版本
	public Node Iterative_Tree_Search(int k) {
		return Iterative_Tree_Search(root, k);
	}
	//二叉树从某个结点x向下搜索k值的方法,返回包含k值的结点,递归版本
	private Node Iterative_Tree_Search(Node x,int k) {
		while(x!=null&&k!=x.key) {
			if(k<x.key) {
				x=x.left;
			}else {
				x=x.right;
			}
		}
		return x;
	}
	
	//搜索二叉树中最小的值,传入root根节点
	public Node Tree_MiniMum() {
		return Tree_MiniMum(root);
	}
	//从某个结点x像下搜索最小的值,返回包含该值的结点
	private Node Tree_MiniMum(Node x) {
		while(x.left!=null) {
			x=x.left;
		}
		return x;
	}
	
	//搜索二叉树中最小大的值,传入root根节点
	public Node Tree_MaxiMum() {
		return Tree_MaxiMum(root);
	}
	//从某个结点x像下搜索最小的值,返回包含该值的结点
	private Node Tree_MaxiMum(Node x) {
		while(x.right!=null) {
			x=x.right;
		}
		return x;
	}
	
	//寻找某个结点x的后继
	public Node Tree_Successor(Node x) {
		if(x.right!=null) {
			return Tree_MiniMum(x.right);
		}
		Node y = x.p;
		while(y!=null&&x==y.right) {
			x=y;
			y=y.p;
		}
		return y;
	}
	
	//寻找某个结点x的前驱,与寻找它的后继Tree_Successor相互对称
	public Node Tree_Predecessor(Node x) {
		if(x.left!=null) {
			return Tree_MaxiMum(x.left);
		}
		Node y = x.p;
		while(y!=null && x==y.left) {
			x=y;
			y=y.p;
		}
		return y;
	}
	
	//搜索二叉树的插入操作,将值为k的结点z插入到搜索二叉树中
	public void Tree_insert(Binary_Search_Tree T,Node z) {
		Node y = null;//搜索指针
		Node x = T.root;//表示树中结点的指针,初始为root
		while(x!=null) {
			y=x;
			if(z.key<x.key) {
				x=x.left;
			}else {
				x=x.right;
			}
		}//循环终止时,x指向一个空的位置,也就是z要插入的位置,而y保留为该位置的父结点
		z.p=y;
		if(y==null) {
			T.root=z;
		}else if(z.key<y.key) {
			y.left=z;
		}else {
			y.right=z;
		}
	}
	
	//搜索二叉树的更换结点操作,将树中以u为根结点的子树更换为新结点以v为根的子树
	public void Transplant(Binary_Search_Tree T,Node u,Node v) {
		if(u.p==null) {
			T.root = v;
		}else if(u==u.p.left) {
			u.p.left=v;
		}else {
			u.p.right=v;
		}
		if(v!=null) {
			v.p=u.p;
		}
	}
	
	//搜索二叉树的删除操作,将树中结点z删除
	public void Tree_Delete(Binary_Search_Tree T,Node z) {
		if(z.left == null) {//第1种情况
			Transplant(T, z, z.right);
		}else if(z.right==null) {//第2种情况
			Transplant(T, z, z.left);
		}else { 
			Node y=Tree_MiniMum(z.right);//直接找到结点z的后继结点y
			if(y.p!=z) {//第4种情况
				Transplant(T, y, y.right);
				y.right=z.right;
				y.right.p=y;
			}else {//第3种情况
				Transplant(T, z, y);
				y.left=z.left;
				y.left.p=y;
			}
		}
	}
}

3 测试:

public class BSTtest {
	public static void main(String[] args) {
		//构建一个搜索二叉树
		Binary_Search_Tree bst = new Binary_Search_Tree();
		//插入数据
		bst.Tree_insert(bst, new Node(2));
		bst.Tree_insert(bst, new Node(3));
		bst.Tree_insert(bst, new Node(4));
		bst.Tree_insert(bst, new Node(6));
		bst.Tree_insert(bst, new Node(7));
		bst.Tree_insert(bst, new Node(13));
		bst.Tree_insert(bst, new Node(9));
		bst.Tree_insert(bst, new Node(15));
		bst.Tree_insert(bst, new Node(17));
		bst.Tree_insert(bst, new Node(18));
		bst.Tree_insert(bst, new Node(20));
		
		System.out.println("搜索二叉树的中序遍历为:");
		bst.Inorder_Tree_Walk();
		System.out.println("搜索二叉树的前序遍历为:");
		bst.Preorder_Tree_Walk();
	
		System.out.println("搜索二叉树的最大值为:"+bst.Tree_MaxiMum().key);
		System.out.println("搜索二叉树的最小值为:"+bst.Tree_MiniMum().key);
		
		System.out.println("删除搜索二叉树中值为13的结点后中序遍历序列为:");
		bst.Tree_Delete(bst, bst.Tree_Search(20));
		bst.Inorder_Tree_Walk();
	}
}

4.结果:
《算法导论》第12章二叉搜索树Java实现