树、二叉树及二叉查找树

原创 2016年05月30日 16:21:18

树状图是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
每个节点有零个或多个子节点;没有父节点的节点称为根节点;每一个非根节点有且只有一个父节点;除了根节点外,每个子节点可以分为多个不相交的子树。
(以下实现代码均在git)

1.  概念和基本术语

1.1树的定义

n (n >= 0) 个结点的有限集。如果 n = 0,称为空树;如果 n > 0,则

1) 有且仅有一个特定的称为根(Root)的结点,根只有直接后继,没有直接前驱;

2) 当n > 1,除根外其它结点划分为 m (m >0) 个互不相交的有限集T1, T2 ,…, Tm,其中每个集合本身又是一棵树,称为根的子树(SubTree)。


1.2相关术语

树的结点:包含一个数据元素及若干指向子树的分支;

孩子结点:结点的子树的根称为该结点的孩子;

双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;

兄弟结点:同一双亲的孩子结点; 堂兄结点:同一层上结点;

祖先结点: 从根到该结点的所经分支上的所有结点子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙

结点层:根结点的层定义为1;根的孩子为第二层结点,依此类推;

树的深度:树中最大的结点层

结点的度:结点子树的个数

树的度: 树中最大的结点度。

叶子结点:也叫终端结点,是度为 0 的结点;

分枝结点:度不为0的结点;

有序树:子树有序的树,如:家族树;

无序树:不考虑子树的顺序;

 

1.3树的其它三种表示法


2.二叉树

定义:一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵分别称为左子树和右子树的、互不相交的二叉树组成。

特点:每个结点至多只有两棵子树(二叉树中不存在度大于2的结点)

五种形态


性质:(见二叉树的五大性质及证明


3. 二叉查找树

       二叉树的一个重要的应用是它们在查找中的使用。假设树中的每个结点存储一项数据。使二叉树成为二叉查找树的性质是,对于树中的每个节点X,它的左子树中所有项的值小于X中的值,而它的右子树中所有项的值大于X中的值。

3.1 二叉查找树的数据结构   

public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {
	//树的节点
	private static class Node<AnyType>{
		AnyType element;     //节点数据
		Node<AnyType> left;  //左孩子
		Node<AnyType> right; //左孩子
		
		Node(AnyType element){
			this(element, null, null);
		}
		
		Node(AnyType element, Node<AnyType> lt, Node<AnyType> rt){
			this.element = element;
			left = lt;
			right = rt;
		}
	}
	
	private Node<AnyType> root;  //根节点
	
	public BinarySearchTree(){
		root = null;
	}
	
	public void makeEmpty(){
		root = null;
	}
	public boolean isEmpty(){
		return root == null;
	}
}

3.2二叉查找树的元素查找

       通过二叉查找树有序的性质,能有效节省查找时的效率,在平均情况下查找的时间复杂度为O(logn),但在最坏的情况下(此时二叉查找树退化成链)查找的时间复杂度会达到O(n)。

	/**
        * 查找元素的内部方法,递归
        * @param x  要查找的元素
        * @param t  子树的根节点
        * @return   是否查找成功
        */
       private boolean contains(AnyType x, Node<AnyType> t){
           if(t == null)
               return false;
            
           int compareResult = x.compareTo(t.element);
            
          if(compareResult < 0)
               return contains(x, t.left);
           else if(compareResult > 0)
               return contains(x, t.right);
           else
               return true;    //匹配
       }

3.3 二叉查找树的最大/最小值查找

       在二叉查找树的性质中可知,对于树中的每个节点X,它的左子树中所有项的值小于X中的值而它的右子树中所有项的值大于X中的值。这样使用递归的方法可很简单地实现最大/最小值的查找。(以下对于最大值和最小值分别使用递归和非递归的形式实现)

     /**
     * 查找树中最小元素,递归
     * @param t
     * @return
     */
    private Node<AnyType> findMin(Node<AnyType> t){
    	if(t == null)
    		return null;
    	else if(t.left == null){
    		return t;
    	}
    	return findMin(t.left);
    }
    /**
     * 查找树中最大元素,非递归实现
     * @param t
     * @return
     */
    private Node<AnyType> findMax(Node<AnyType> t){
    	if(t != null){
    		while(t.right != null){
    			t = t.right;
    		}
    	}
    	return t;
    }

3.4 二叉查找树节点的插入

       二叉查找树插入的实现与查找相似,即找到对应位置在执行插入操作。

    /**
     * 将元素插入到二叉查找树
     * @param x  要查找的元素
     * @param t  子树的根节点
     * @return   插入后的树的根节点
     */
    private Node<AnyType> insert(AnyType x, Node<AnyType> t) {
    	if(t == null)
    		return new Node<>(x, null, null);   //递归最后找到了属于自己的位置
    	
    	int compareResult = x.compareTo(t.element);
    	if(compareResult < 0)
    		t.left = insert(x, t.left);
    	else if(compareResult > 0)
    		t.right = insert(x, t.right);
    	else
    		;    //什么都不做
    	
		return t;
	}

3.5 二叉查找树节点的删除

   二叉查找树节点的删除有两种情况:

1.被删除的节点只有一个儿子,则该结点可以在其父节点调整自己的链后删除;(若该节点是树叶的情况等同,此时赋值的值为null)

2.被删除的节点只有两个儿子,用其右子树的最小的数据代替该节点的数据,并递归第删除那个节点。

    private Node<AnyType> remove(AnyType x, Node<AnyType> t) {
    	if(t == null)
    		return t;     //未找到该元素
    	
    	int compareResult = x.compareTo(t.element);
    	
    	if(compareResult < 0)
    		t.left = remove(x, t.left);
    	else if(compareResult > 0)
    		t.right = remove(x, t.right);
    	else if(t.left != null && t.right != null){   //要删除的节点有两个孩子
    		t.element = findMin(t.right).element;
    		t.right = remove(t.element, t.right);
    	}
    	else
    		t = (t.left != null)?t.left:t.right;  //要删除的节点有一个孩子或无孩子
    	
    	return t;
	}


4. 二叉查找树的遍历

4.1中序遍历

       中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。

    private void inOrder(Node<AnyType> root){
    	if(root != null){
    		inOrder(root.left);
    		System.out.print(root.element + " ");
    		inOrder(root.right);
    	}
    }

4.2 先序遍历

       首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树,如果二叉树为空则返回。

    private void preOrder(Node<AnyType> root){
    	if(root != null){
    		System.out.print(root.element + " ");
    		preOrder(root.left);
    		preOrder(root.right);
    	}
    }

4.3 后序遍历

       后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。

    private void postOrder(Node<AnyType> root){
    	if(root != null){
    		postOrder(root.left);
    		postOrder(root.right);
    		System.out.print(root.element + " ");
    	}
    }

4.4 层序遍历

       设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

    /**
     * 层次遍历二叉树(使用队列)
     * 描述:先将根节点放入队列中,然后每次都从队列中取出一个节点打印,
     *     若这个节点有子节点,则将它的子节点放入队列尾,直到队列为空
     */
    public void layerTranverse(){
    	if(this.root == null){
    		return;
    	}
    	
    	Queue<Node<AnyType>> q = new LinkedList<Node<AnyType>>();
    	q.add(this.root);
    	while(!q.isEmpty()){
    		Node<AnyType> n = q.poll();
    		System.out.print(n.element + " ");
    		if(n.left != null){
    			q.add(n.left);
    		}
    		if(n.right != null){
    			q.add(n.right);
    		}
    		
    	}
    }

4.5 遍历结果对比




参考资料:

1. 《数据结构与算法分析》

2. 《Java程序员面试笔试宝典》

3. Boss的PPT

版权声明:本文为博主原创文章,若要转载请注明文章出处。

相关文章推荐

程序员面试100题(算法)之把二叉查找树转变成排序的双向链表(含二叉树前序创建、递归)

// Test2.cpp : 定义控制台应用程序的入口点。 //程序员面试100题(算法)之把二叉查找树转变成排序的双向链表 #include "stdafx.h" #include #i...

检查一颗二叉树是否是二叉查找树

中序遍历法首先,最直观的一种算法就是进行一次中序遍历,然后将每个节点的值保存在一个数组中,然后这个数组是有序的,那么这颗树就是一个二叉查找树。小问题但是这个算法有一个问题,那就是对于存在重复值的二叉查...

组合二叉树[二叉查找树+大根堆]

考察二叉树的构造,搜索树,大根堆的相关性质

判断二叉查找树是否是平衡二叉树(代码)

递归解法: (1)如果二叉树为空,返回真 (2)如果二叉树不为空,如果左子树和右子树都是AVL树并且左子树和右子树高度相差不大于1,返回真,其他返回假参考代码: /****************...

数据结构-二叉树和二叉查找树

先按树-二叉树-二叉查找树的顺序解释会比较清楚。 一,树 树(Tree)是n(n≥0)个结点的有限集。在任意一棵非空树中: (1)有且仅有一个特定的被称为根(Root)的结点; (2)当n>1...

二叉查找树、平衡二叉树

树结构练习——排序二叉树的中序遍历 Time Limit: 1000MS Memory Limit: 65536KB Problem Description 在树结构中,有一种特殊的二叉树叫做排序...

二叉树系列---求包含n个节点的二叉查找树的种类数

题目求包含n个节点的二叉树的种类数;方法1设dp[i]表示共有i个节点时,能产生的BST树的个数 n == 0 时,空树的个数必然为1,因此dp[0] = 1 n ==...

二叉树和二叉查找树

1.二叉树和二叉查找树1)什么是树? 树由一组以边连接的节点组成,一棵树最上面的节点称为 根节点,如果一个节点下面连接多个节点,那么该节点称为父节点,它下面的节点称为子 节点。一个节点可以有 0 个...

树、二叉树、二叉查找树

利用表数据结构来进行数据操作时,其访问方式是线性的,当数据量较大时,需要的处理时间会很大,不宜使用,这时我们需要一种新的数据结构,来降低时间的开销,这种数据结构就是树(tree)。...
  • Mr_Avin
  • Mr_Avin
  • 2016年12月04日 10:59
  • 362

数据结构与算法分析-树、二叉树、二叉查找树

作者:xiabodan 出处:http://blog.csdn.net/xiabodan 二叉树二叉树的申明:struct node { int data; struct node ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:树、二叉树及二叉查找树
举报原因:
原因补充:

(最多只允许输入30个字)