“树”总结篇(一)

一:数的概念

1.数是一种特殊的数据结构,它可以用来描述有分支的结构,是由一个或者一个以上的节点所组成的有限的集合。
在这里插入图片描述
2.结点的度:结点拥有子树的个数。
3.树的度:树中所有结点的度的最大值。
4.叶结点:度为0的结点,也成为终端结点。
5.子结点:结点子数的根(即直接后继)称为该结点的子结点。
6.双亲节点:结点是其子树的双亲。
7.兄弟结点:同一双亲孩子结点之间互称兄弟结点。
8.结点的层次:结点的层次从树根开始定义,根为第一层,根的孩子为第二层,若某结点在第k层,则其孩子就在第k+1层,以此类推。
9:树的形态:
在这里插入图片描述

二:二叉数

1.概念

由一个由有限节点所组成的集合,此集合可以为空集合,或由一个树根及左右两个子树所组成。简单地说,二叉树最多只能有两个子节点,就是度小于或等于2。

2.满二叉树

如果二叉树的高度为h,树的节点树为2h-1, h>=0,则称之为“满二叉树”
在这里插入图片描述

3.完全二叉树

在这里插入图片描述

4.二叉树的性质

1)在二叉树的第n层上至多有2的(n-1)次方 个节点
在这里插入图片描述
2)深度为K的二叉树至多有2的k次方减1个节点
在这里插入图片描述
3)具有n个节点的完全二叉树的深度K为:
K = log2n+1
在这里插入图片描述

三:二叉查找树

1.其左子树(left subtree)下的每个后代节点(descendant node)的值都小于节点 n 的值;
2.其右子树(right subtree)下的每个后代节点的值都大于节点 n 的值
在这里插入图片描述

构建二叉查找树

定义结点:

/**
	 * bst树的节点
	 */

	public static class TreeNode {
		int val;
		TreeNode left;
		TreeNode right;

		public TreeNode(int val, TreeNode left, TreeNode right) { // 构造方法

			this.val = val;
			this.left = left;
			this.right = right;
		}

		@Override
		public String toString() {
			return "TreeNode [val=" + val + ", left=" + left + ", right=" + right + "]";
		}
	}

1.迭代法创建

public class BST {

	private TreeNode root; // 根
	private int size; // 容量大小

	public TreeNode getRoot() {
		return this.root;
	}

	/**
	 * 添加操作--add (迭代法创建树)
	 * 
	 * @param val
	 */
	public void add(int val) {
		TreeNode tmp = new TreeNode(val, null, null);

		if (this.root == null) { // 空树时
			root = tmp;
			this.size++;
		} else { // 不为空时
			TreeNode curr = root;
			while (true) {
				if (val < curr.val) { // 左子树
					if (curr.left == null) { // 为空时挂节点
						curr.left = tmp;
						this.size++;
						break;
					}
					curr = curr.left;// 继续往左移动
				} else if (val > curr.val) { // 右子树
					if (curr.right == null) {
						curr.right = tmp;
						this.size++;
						break;
					}
					curr = curr.right; // 继续往右走
				}
			}

		}

	}

测试:

@Test
	public void test() {
		BST tree = new BST();
		tree.add(6);
		tree.add(3);
		tree.add(8);
		tree.add(7);
		tree.add(2);
		tree.add(4);
		System.out.println(tree);
		//结果>>>BST [root=TreeNode [val=6, left=TreeNode [val=3, left=TreeNode [val=2, left=null, right=null], right=TreeNode [val=4, left=null, right=null]], right=TreeNode [val=8, left=TreeNode [val=7, left=null, right=null], right=null]], size=6]

2.递归法创建

/**
	 * 递归法--创建树
	 * 
	 * @param root
	 * @return
	 */
	public TreeNode insert(TreeNode curr, int val) {
		if (curr == null) { // 终止条件
			return new TreeNode(val, null, null);
		} else if (val < curr.val) { // 左子树
			curr.left = insert(curr.left, val);
		} else if (val > curr.val) { // 右子树
			curr.right = insert(curr.right, val);
		}
		return curr;

	}

测试:

/**
		 * 递归测试
		 */
		BST tree = new BST();
		TreeNode root = tree.getRoot();
		root = tree.insert(root, 6);
		root = tree.insert(root, 3);
		root = tree.insert(root, 8);
		root = tree.insert(root, 7);
		root = tree.insert(root, 2);
		root = tree.insert(root, 4);
		System.out.println(root);
		//结果>>>TreeNode [val=6, left=TreeNode [val=3, left=TreeNode [val=2, left=null, right=null], right=TreeNode [val=4, left=null, right=null]], right=TreeNode [val=8, left=TreeNode [val=7, left=null, right=null], right=null]]

二叉查找树的遍历

1.前序

1)递归写法:

/**
	 * 前序----根-左-右
	 */

	public void preOrder(TreeNode root) {
		if (root == null) {
			return;
		}
		System.out.println(root.val + " "); // 根
		preOrder(root.left);// 左
		preOrder(root.right);// 右
	}

测试:

@Test
	public void test() {
		BST tree = new BST();
		tree.add(6);
		tree.add(3);
		tree.add(8);
		tree.add(7);
		tree.add(2);
		tree.add(4);

		System.out.println("前序:");
		tree.preOrder(tree.getRoot());

在这里插入图片描述
2)非递归写法:

public class QianXudemo {
	/**
	 * 迭代法--前序
	 */
	public List<Integer> qianXu(TreeNode root) {
		List<Integer> list = new ArrayList<>();
		Stack<TreeNode> stack = new Stack<>(); // 构建辅助栈
		if (root == null) { // 空树
			return list;
		}
		stack.push(root); // 入栈操作
		while (stack != null) { // 终止条件
			TreeNode tmp = stack.pop(); // 弹出当前元素
			list.add(tmp.val);
			if (tmp.right != null) {
				stack.push(tmp.right);
			} else if (tmp.left != null) {
                stack.push(tmp.left);
			}
		}
		return list;
	}
}

2.中序

1)递归写法:

/**
	 * 中序----左-根-右
	 */

	public void inOrder(TreeNode root) {
		if (root == null) {
			return;
		}
		inOrder(root.left);// 左
		System.out.println(root.val + " "); // 根
		inOrder(root.right);// 右
	}

测试:

@Test
	public void test() {
		BST tree = new BST();
		tree.add(6);
		tree.add(3);
		tree.add(8);
		tree.add(7);
		tree.add(2);
		tree.add(4);

		System.out.println("中序:");
		tree.inOrder(tree.getRoot());
		

在这里插入图片描述
2)非递归写法:

public class ZhongXudemo {
	/**
	 * 迭代法--中序
	 */
    public List<Integer> zhongXu(TreeNode root){
    	List<Integer> list = new ArrayList<>();
    	Stack<TreeNode> stack = new Stack<>(); //构建辅助栈,利用其先入后出的特点
    	TreeNode tmp = root;
    	While(tmp!=null || !stack.isempty()){
    		while(tmp!=null) {
    			stack.push(tmp);
    			tmp = tmp.left;  //遍历左子树
    		}
    		tmp = stack.pop(); //弹出栈
    		list.add(tmp.val);  //存入数组中,加入当前节点
    		tmp = tmp.right;  //遍历右子树
    	}
    	return list;
    }
}

3.后序

1)递归写法:

/**
	 * 后序----左-右-根
	 */

	public void postOrder(TreeNode root) {
		if (root == null) {
			return;
		}
		postOrder(root.left);
		postOrder(root.right);
		System.out.println(root.val + " "); // 根
	}

测试:

@Test
	public void test() {
		BST tree = new BST();
		tree.add(6);
		tree.add(3);
		tree.add(8);
		tree.add(7);
		tree.add(2);
		tree.add(4);
		System.out.println("后序:");
		tree.postOrder(tree.getRoot());

在这里插入图片描述
2)非递归写法:

public class HouXuDemo {
	public List<Integer> houXu(TreeNode root) {
		List<Integer> list = new ArrayList<>();
		Stack<TreeNode> stack = new Stack<TreeNode>();
		TreeNode tmp = root;
		while (tmp != null || !stack.isEmpty()) {
			while (tmp != null) {
				stack.push(tmp);
				tmp = tmp.left; // 开始遍历左子树
			}
			TreeNode t = stack.peek(); // 获得当前的栈顶元素
			if (t.right == null) { // 当前栈顶元素没有右节点
				list.add(stack.pop().val); // 将其加入list数组中
			} else {
				// 将当前结点的右节点保存起来,并将其置为null
				tmp = t.right;
				t.right = null;
			}
		}
		return list;
	}
}

4.层级优先—广度优先

/**
	 * 层级优先---广度优先
	 */

	public void levelOrder(TreeNode root) {
		if (root == null) {
			return;
		}
		Queue<TreeNode> q = new LinkedList<>();
		q.offer(root); // 将root存入队列中

		while (!q.isEmpty()) { // 终止条件
			TreeNode tmp = q.poll();// 弹出
			System.out.print(tmp.val + "    ");
			if (tmp.left != null) {
				q.offer(tmp.left);
			}
			if (tmp.right != null) {
				q.offer(tmp.right);
			}
		}
	}

测试:

@Test
	public void test() {
		BST tree = new BST();
		tree.add(6);
		tree.add(3);
		tree.add(8);
		tree.add(7);
		tree.add(2);
		tree.add(4);
		
		System.out.println("层级优先:");
		tree.levelOrder(tree.getRoot());

在这里插入图片描述

二叉查找树的删除

代码实例:

/**
	 * 二叉树删除
	 * 
	 * @param root
	 * @param val
	 * @return
	 */
	public TreeNode delete(TreeNode root, int val) {
		if (root.val == val) { // 找到要删除的数,要删除的数与root相等时
			System.out.println("找到要删除节点:" + root);
			if (root.left == null && root.right == null) { // 左右都无节点
				return null;
			} else if (root.left == null) { // 有右节点
				return root.right;
			} else if (root.right == null) { // 有左节点
				return root.left;
			} else if (root.left != null && root.right != null) { // 有左右两个节点
				TreeNode min = minNode(root.right);
				root.val = min.val;
				root.right = delete(root.right, min.val);
			}
		} else if (val < root.val) { // 找到要删除的数,要删除的数小于root时---左子树
			root.left = delete(root.left, val);
		} else if (val > root.val) {  // 找到要删除的数,要删除的数大于root时---右子树
			root.right = delete(root.right, val);
		}
		return root;

	}

	public TreeNode minNode(TreeNode node) { // 找到最小节点
		while (node.left != null) {
			node = node.left;
		}
		return node;
	}

测试:

@Test
	public void test() {
		BST tree = new BST();
		tree.add(6);
		tree.add(3);
		tree.add(8);
		tree.add(7);
		tree.add(2);
		tree.add(4);
		
		
		System.out.println("删除:");
		tree.delete(tree.getRoot(), 4);
		System.out.println(tree);

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值