数据结构之树(五)

 :是一种递归定义的数据结构。树( Tree )是树结构的简称,它是一种重要的非线性数据结构。
树或者是一个空树,即不含有任何的结点(元素),或者是一个非空树,即至少含有一个结点。


    :在一棵非空树中,它有且仅有一个节点。
    子树:在一棵非空树中,除根外其余所有结点分属于 m 个( m ≥ 0 )不相交的集合。每个集合又
构成一棵树,称为根结点的 子树。


    树的递归定义
      树 (Tree) 是 n(n≥0) 个结点的有限集 T , T 为空时称为空树,否则它满足如下两个条件:
      (1) 有且仅有一个特定的称为根 (Root) 的结点;
      (2) 其余的结点可分为 m(m≥0) 个互不相交的子集 Tl , T2 , … , Tm ,其中每个子集本身又
          是一棵树,并称其为根的子树 (Subree) 。
          注意:树的递归定义刻画了树的固有特性:一棵非空树是由若干棵子树构成的,而子树又可由
 若干棵更小的子树构成。
      树的表示: 树形图表示是树结构的主要表示方法。其他还有广义表、集合图、凹入图三种表示形式。

 

    结点 (node) :表示树中的元素,包括数据项及若干指向其子树的分支。
    结点的度 (degree) :树中的一个结点拥有的子树数称为该结点的度 (Degree) 。
    叶子 (leaf) :度为 0 的结点。
    孩子 (child) :结点子树的根称为该结点的孩子。
    双亲 (parents) :孩子结点的上层结点叫该结点的。
    兄弟 (sibling) :同一双亲的孩子。


    树的度:一棵树中最大的结点度数。
    结点的层次 (level) :从根结点算起,根为第一层,它的孩子为第二层……。
    深度 (depth) :树中结点的最大层次数。


    有序树:子树的位置自左向右有次序关系的称为有序树,顺序决定了大小,孩子的次序不能改变
    无序树:子树的位置自左向右无次序关系的称为无序树。
    森林 (Forest) 是 m(m≥0) 棵互不相交的树的集合。树和森林的概念相近。删去一棵树的根,就
得到一个森林;反之,加上一个结点作树根,森林就变为一棵树。


    路径:若树中存在一个结点序列 k1 , k2 , … , ki ,使得 ki 是 ki+1 的双亲 (1≤i<j) ,则称该结点序列是从 k1 到 kj 的一条路径 (Path) 或道路。
    路径的长度:指路径所经过的边 ( 即连接两个结点的线段 ) 的数目,等于 j-1。
    祖先: 若树中结点 k 到 ks 存在一条路径,则称 k 是 ks 的 祖先 (Ancestor) , ks 是 k 的 子孙 (Descendant) 。结点 k 的祖先和子孙不包含结点 k 本身。


    结点的层数: (Level) 从根起算:根的层数为 1 ,其余结点的层数等于其双亲结点的层数加 1 。
双亲在同一层的结点互为堂兄弟。树中结点的最大层数称为树的高度 (Height) 或深度 (Depth) 。很多
文献中将树根的层数定义为 0。

 

    树形结构的逻辑特征
    树形结构的逻辑特征可用树中结点之间的父子关系来描述:
      1 、树中任一结点都可以有零个或多个直接后继 ( 即孩子 ) 结点,但至多只能有一个直接前趋
         ( 即双亲 ) 结点。
      2、树中只有根结点无前趋,它是开始结点;叶结点无后继,它们是终端结点。
      3、祖先与子孙的关系是对父子关系的延拓,它定义了树中结点之间的纵向次序。
      4、有序树中,同一组兄弟结点从左到右有长幼之分。
         对这一关系加以延拓,规定若 k1 和 k2 是兄弟,且 k1 在 k2 的左边,则 k1 的任一子孙都在 k2 的任一子孙的左边,那么就定义了树中结点之间的横向次序。
 

    二叉树 :指树的度为 2 的有序树。是最简单的一种树结构,在计算机领域有着广泛的应用。
    二叉树的递归定义:二叉树或者是一棵 空树 ,或者是一棵由一个 根结点和两棵互不相交的分别
称根的 左子树 和 右子树 所组成的 非空树 ,左子树和右子树又同样都是一棵二叉树。 二叉树中,
每个结点的左子树的根结点被称为该结点的 左孩子 ( left child ) , 右子树的根结点被称为 右孩子
( left child )。


    满二叉树: 深度为 K 且含有2K -1 个结点的二叉树,当树中的每一层都满时成为漫二叉树。


    完全二叉树:在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者
在最右边缺少连续若干个结点,则称此树为完全二叉树。

 

   树的抽象数据类型定义:
   ADT Tree{
       数据对象D:D是具有相同性质的数据元素的集合。
       数据关系R:1,存在一个唯一的根元素root,无前驱;
                  2,除root外,D中的每个结点都有且仅有一个前驱。

       基本操作:1、getSize();
                 2、getRoot();
                 3、getParent(x);
                 4、getFirstChild(x);
                 5、getNextSibling(x);
                 6、getHeight(x);
                 7、insertChild(x,child);
                 8、deleteChild(x,i);
                 9、preOrder(x) 先序
                    postOrder(x) 后序
                    levelOrder(x) 按层遍历x为根的树。
   }ADT Tree

  

   二叉树的抽象数据类型定义:
   ADT BinaryTree{
       数据对象D:D是具有相同性质的数据元素的集合。
       数据关系R:1,存在一个唯一的根元素root,无前驱;
                  2,除root外,D中的每个结点都有且仅有一个前驱。

       基本操作:1、getSize();
                 2、isEmpty();
                 3、getRoot();
                 4、getHeigth();
                 5、find(e);
                 6、preOrder() 先序
                    inOrder() 中序
                    postOrder() 后序
                    levelOrder() 按层遍历x为根的树。
   }ADT BinaryTree

 

二叉树结点的定义:

 二叉树存储结构结点定义

public interface Node {
  //获取结点数据域
  public Object getData();
  //设置结点数据域
  public void setData(Object obj);
}


 

public class BinTreeNode implements Node {

	private Object data; //数据域
	private BinTreeNode parent; //父结点
	private BinTreeNode lChild; //左孩子
	private BinTreeNode rChild; //右孩子
	private int height; //以该结点为根的子树的高度
	private int size; //该结点子孙数(包括结点本身)

	public BinTreeNode() {
		this(null);
	}

	public BinTreeNode(Object e) {
		data = e;
		parent = lChild = rChild = null;
		height = 0;
		size = 1;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object obj) {
		data = obj;
	}

	//判断是否有父亲
	public boolean hasParent() {
		return parent != null;
	}

	//判断是否有左孩子
	public boolean hasLChild() {
		return lChild != null;
	}

	//判断是否有右孩子
	public boolean hasRChild() {
		return rChild != null;
	}

	//判断是否为叶子结点
	public boolean isLeaf() {
		return !hasLChild() && !hasRChild();
	}

	//判断是否为某结点的左孩子
	public boolean isLChild() {
		return (hasParent() && this == parent.lChild);
	}

	//判断是否为某结点的右孩子
	public boolean isRChild() {
		return (hasParent() && this == parent.rChild);
	}

	//取结点的高度,即以该结点为根的树的高度
	public int getHeight() {
		return height;
	}

	//更新当前结点及其祖先的高度
	private void updateHeight() {
		int newH = 0;//新高度初始化为0,高度等于左右子树高度加1中大的
		if (hasLChild())
			newH = Math.max(newH, 1 + getLChild().getHeight());
		if (hasRChild())
			newH = Math.max(newH, 1 + getRChild().getHeight());
		if (newH == height)
			return; //高度没有发生变化则直接返回
		height = newH; //否则更新高度
		if (hasParent())
			getParent().updateHeight(); //递归更新祖先的高度
	}

	//取以该结点为根的树的结点数
	public int getSize() {
		return size;
	}

	//更新当前结点及其祖先的子孙数
	private void updateSize() {
		size = 1; //初始化为1,结点本身
		if (hasLChild())
			size += getLChild().getSize(); //加上左子树规模
		if (hasRChild())
			size += getRChild().getSize(); //加上右子树规模
		if (hasParent())
			getParent().updateSize(); //递归更新祖先的规模
	}

	//取父结点
	public BinTreeNode getParent() {
		return parent;
	}

	//断开与父亲的关系
	private void sever() {
		if (!hasParent())
			return;
		if (isLChild())
			parent.lChild = null;
		else
			parent.rChild = null;
		parent.updateHeight(); //更新父结点及其祖先高度
		parent.updateSize(); //更新父结点及其祖先规模
		parent = null;
	}

	//取左孩子
	public BinTreeNode getLChild() {
		return lChild;
	}

	//设置当前结点的左孩子,返回原左孩子
	public BinTreeNode setLChild(BinTreeNode lc) {
		BinTreeNode oldLC = this.lChild;
		if (hasLChild()) {
			lChild.sever();
		} //断开当前左孩子与结点的关系
		if (lc != null) {
			lc.sever(); //断开lc与其父结点的关系
			this.lChild = lc; //确定父子关系
			lc.parent = this;
			this.updateHeight(); //更新当前结点及其祖先高度
			this.updateSize(); //更新当前结点及其祖先规模
		}
		return oldLC; //返回原左孩子
	}

	//取右孩子
	public BinTreeNode getRChild() {
		return rChild;
	}

	//设置当前结点的右孩子,返回原右孩子
	public BinTreeNode setRChild(BinTreeNode rc) {
		BinTreeNode oldRC = this.rChild;
		if (hasRChild()) {
			rChild.sever();
		} //断开当前右孩子与结点的关系
		if (rc != null) {
			rc.sever(); //断开lc与其父结点的关系
			this.rChild = rc; //确定父子关系
			rc.parent = this;
			this.updateHeight(); //更新当前结点及其祖先高度
			this.updateSize(); //更新当前结点及其祖先规模
		}
		return oldRC; //返回原右孩子
	}
}


三叉链表存储下的二叉树的实现:(三叉链表存储是指:二叉树的结点的存储单元包含4个域,1、数据域,2、左孩子域,3、父亲域,4、右孩子域。)

三叉链表存储下的二叉树的实现BinaryTreeLinked

public interface BinTree {
	//返回树的规模
	public int getSize();

	//判断树是否为空
	public boolean isEmpty();

	//返回根结点引用
	public BinTreeNode getRoot();

	//获取树的高度
	public int getHeight();

	//在树中查找元素e,返回其所在结点
	public BinTreeNode find(Object e);

	//先序遍历二叉树
	public Iterator preOrder();

	//中序遍历二叉树
	public Iterator inOrder();

	//后序遍历二叉树
	public Iterator postOrder();

	//按层遍历二叉树
	public Iterator levelOrder();
}


 

                          三叉链表存储下的二叉树的实现BinaryTreeLinked

public interface BinTree {
  // 返回树的规模
  public int getSize();
  // 判断树是否为空
  public boolean isEmpty();
  // 返回根结点引用
  public BinTreeNode getRoot();
  // 获取树的高度
  public int getHeight();
  // 在树中查找元素e,返回其所在结点
  public BinTreeNode find(Object e);
  // 先序遍历二叉树
  public Iterator preOrder();
  // 中序遍历二叉树
  public Iterator inOrder();
  // 后序遍历二叉树
  public Iterator postOrder();
  // 按层遍历二叉树
  public Iterator levelOrder();
}

public class BinaryTreeLinked implements BinTree {
  protected BinTreeNode root;
  protected Strategy strategy;
 
  public BinaryTreeLinked(){ this(null); }
  public BinaryTreeLinked(BinTreeNode root) { this(root,new DefaultStrategy());}
  public BinaryTreeLinked(BinTreeNode root, Strategy strategy){
    this.root = root;
    this.strategy = strategy;
  }

  // 返回树的规模
  public int getSize() {
    return root==null?0:root.getSize();
  }

  // 判断树是否为空
  public boolean isEmpty() { return root==null;}

  // 返回根结点引用
  public BinTreeNode getRoot() { return root;}

  // 获取树的高度
  public int getHeight() { return isEmpty()?-1:root.getHeight();}

  // 在树中查找元素e,返回其所在结点
  public BinTreeNode find(Object e) {
    return searchE(root,e);
  }
  // 递归查找元素e
  private BinTreeNode searchE(BinTreeNode rt, Object e) {
    if (rt==null) return null;
    if (strategy.equal(rt.getData(),e)) return rt;  // 如果是根结点,返回根
    BinTreeNode v = searchE(rt.getLChild(),e);      // 否则在左子树中找
    if (v==null) v = searchE(rt.getRChild(),e);     // 没找到,在右子树中找
    return v;
  }
 
  // 先序遍历二叉树
  public Iterator preOrder() {
    LinkedList list = new LinkedListDLNode();
    preOrderRecursion(this.root,list);
    return list.elements();
  }
  // 先序遍历的递归算法
  private void preOrderRecursion(BinTreeNode rt, LinkedList list){
    if (rt==null) return;          // 递归基,空树直接返回
    list.insertLast(rt);          // 访问根结点
    preOrderRecursion(rt.getLChild(),list);  // 遍历左子树
    preOrderRecursion(rt.getRChild(),list);  // 遍历右子树
  }
  // 先序遍历的非递归算法
  private void preOrderTraverse(BinTreeNode rt, LinkedList list){
    if (rt==null) return;
    BinTreeNode p = rt;
    Stack s = new StackSLinked();
    while (p!=null){
      while (p!=null){       // 向左走到尽头
        list.insertLast(p);  // 访问根
        if (p.hasRChild()) s.push(p.getRChild());  // 右子树根结点入栈
        p = p.getLChild();             
      }
      if (!s.isEmpty()) p = (BinTreeNode)s.pop();  // 右子树根退栈遍历右子树
    }
  }
 
  // 中序遍历二叉树
  public Iterator inOrder(){
    LinkedList list = new LinkedListDLNode();
    inOrderRecursion(this.root,list);
    return list.elements();
  }
  // 中序遍历的递归算法
  private void inOrderRecursion(BinTreeNode rt, LinkedList list){
    if (rt==null) return;                   // 递归基,空树直接返回
    inOrderRecursion(rt.getLChild(),list);  // 遍历左子树
    list.insertLast(rt);                    // 访问根结点
    inOrderRecursion(rt.getRChild(),list);  // 遍历右子树
  }
  // 中序遍历的非递归算法
  private void inOrderTraverse(BinTreeNode rt, LinkedList list){
    if (rt==null) return;
    BinTreeNode p = rt;
    Stack s = new StackSLinked();
    while (p!=null||!s.isEmpty()){
      while (p!=null){    // 一直向左走
        s.push(p);        // 将根结点入栈
        p = p.getLChild();
      }
      if (!s.isEmpty()){
        p = (BinTreeNode)s.pop();// 取出栈顶根结点访问之
        list.insertLast(p);
        p = p.getRChild();       // 转向根的右子树进行遍历
      }// if
    }// out while
  }
 
  // 后序遍历二叉树
  public Iterator postOrder(){
    LinkedList list = new LinkedListDLNode();
    postOrderRecursion(this.root,list);
    return list.elements();
  }
  // 后序遍历的递归算法
  private void postOrderRecursion(BinTreeNode rt, LinkedList list){
    if (rt==null) return;                   // 递归基,空树直接返回
    postOrderRecursion(rt.getLChild(),list);// 遍历左子树
    postOrderRecursion(rt.getRChild(),list);// 遍历右子树
    list.insertLast(rt);                    // 访问根结点
  }
  // 后序遍历的非递归算法
  private void postOrderTraverse(BinTreeNode rt, LinkedList list){
    if (rt==null) return;
    BinTreeNode p = rt;
    Stack s = new StackSLinked();
    while(p!=null||!s.isEmpty()){
      while (p!=null){    // 先左后右不断深入
        s.push(p);        // 将根节点入栈
        if (p.hasLChild()) p = p.getLChild();
        else p = p.getRChild();
      }
      if (!s.isEmpty()){
        p = (BinTreeNode)s.pop();    // 取出栈顶根结点访问之
        list.insertLast(p);
      }
      // 满足条件时,说明栈顶根节点右子树已访问,应出栈访问之
      while (!s.isEmpty()&&((BinTreeNode)s.peek()).getRChild()==p){
        p = (BinTreeNode)s.pop();
        list.insertLast(p);
      }
      // 转向栈顶根结点的右子树继续后序遍历
      if (!s.isEmpty()) p = ((BinTreeNode)s.peek()).getRChild();
      else p = null;
    }
  }
 
  // 按层遍历二叉树
  public Iterator levelOrder(){
    LinkedList list = new LinkedListDLNode();
    levelOrderTraverse(this.root,list);
    return list.elements();
  }
  // 使用对列完成二叉树的按层遍历
  private void levelOrderTraverse(BinTreeNode rt, LinkedList list){
    if (rt==null) return;
    Queue q = new QueueArray();
    q.enqueue(rt);      // 根结点入队
    while (!q.isEmpty()){
      BinTreeNode p = (BinTreeNode)q.dequeue();  // 取出队首结点p并访问
      list.insertLast(p);
      if (p.hasLChild()) q.enqueue(p.getLChild());// 将p的非空左右孩子依次入队
      if (p.hasRChild()) q.enqueue(p.getRChild());
    }
  }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值