链式结构实现二叉树
2014-07-15 18:41
323 查看
相关术语:
平衡树,非平衡树,完全数,满树。
实现策略:
1)数组实现
这个还是非常重要的,有时间写一下,先用链来写
元素n的(从0开始按层编号)左子树编号为2n+1,右子树编号为2n+2,数学证明就略了,用这个来控制下标
2)模拟链式实现
3)链式实现
树是一种非线性结构,那么跟前不一样,必须根据你的需求来构造新的节点才能满足树中的节点特征:
下面是一个实现了一些基本操作的二叉树的ADT:主要是三种遍历方式
下面来实现:
维护一个根节点和count变量来记录总共的节点数,以及下面的构造方法:
主要来看一下遍历的实现,把遍历写成一个迭代器(在链表里写了很多代码,感觉很憋屈,很多地方都花在遍历和迭代上,就是因为没有去实现Iterator)
在遍历中,要用到队列,先来看下队列迭代器是怎么实现的:
在前面写的队列LinkedQueue中,添加一个返回值为Iterator的方法:
它实际上是返回另一个继承了Iterator类的类的对象,这个对象的构造函数一般来说是由LinkedQueue里的成员变量组成的(因为要实现Iterator里面的方法):
上面说明了怎么去实现一个数据结构的迭代器,关键在于去实现特定于自身数据结构的Iterator方法(hasNext,next,remove)
在树的遍历中,需要借助于队列的迭代器,来返回一个树的迭代器,将树中元素按照遍历规则入队,最后返回队列的迭代器,这个迭代器就是树的迭代器。
中序遍历迭代器的实现(前序后序类似):借助于一个private的支持方法来将树中元素按序进队:
将遍历写成迭代迭代器会有利于很多后序操作,当然,也可以直接写一个遍历输出元素:
其他操作参见注释,不再分析实现,清单代码:
你会发现,并没有去实现add和delete操作,因为在具体的应用需求之前,并不知道该怎么去添加和删除,它不像线性结构,添加和删除后是要调整树的形状的。
由于没有写一个addleft,addright方法,构造一个树来测试显得很冗长,在main方法前面好多行,构造了下面的二叉树:
结果如下:
树的大小是: 7
树为空吗?: false
中序遍历结果为:
3 2 4 1 5 7 6
前序遍历结果为:
1 2 3 4 5 6 7
后序遍历结果为:
3 4 2 7 6 5 1
null
包含元素6吗?: true
包含元素8吗?: false
删除左子树后中序遍历结果为:
1 5 7 6
平衡树,非平衡树,完全数,满树。
实现策略:
1)数组实现
这个还是非常重要的,有时间写一下,先用链来写
元素n的(从0开始按层编号)左子树编号为2n+1,右子树编号为2n+2,数学证明就略了,用这个来控制下标
2)模拟链式实现
3)链式实现
树是一种非线性结构,那么跟前不一样,必须根据你的需求来构造新的节点才能满足树中的节点特征:
package Tree; public class BinaryTreeNode { protected Object element; protected BinaryTreeNode left,right; public BinaryTreeNode(Object element)//用元素来构造一个结点 { this.element = element; left = null; right = null; } public int numChildren(){//返回结点的子树上结点的个数 int count = 0; if(left != null) count = 1 + left.numChildren(); if(right != null) count = count + 1 + right.numChildren(); return count; } }
下面是一个实现了一些基本操作的二叉树的ADT:主要是三种遍历方式
package Tree; import java.util.Iterator;//引入迭代器后,对于遍历就直接将遍历的方法写在了迭代器中 public interface BinaryTreeADT { public int size(); public boolean isEmpty(); public boolean contains(Object element); public void removeLeftSubtree();//删除左子树 public void removeRightSubtree();//删除右子树 public Object find(Object targetelement);//找到某个元素并返回其引用 public String toString();//返回树的字符串表示 public Iterator iteratorInorder();//返回中序遍历的迭代器 public Iterator PreInorder();//返回前序遍历的迭代器 public Iterator PostInorder();//返回后序遍历的迭代器 //public Iterator LevelInorder();//返回层次遍历的迭代器 }
下面来实现:
维护一个根节点和count变量来记录总共的节点数,以及下面的构造方法:
private int count; protected BinaryTreeNode root; //3个构造方法 public BinaryTree() { root = null; count = 0; } public BinaryTree(Object element) { root = new BinaryTreeNode(element); count = 1; } public BinaryTree(Object element,BinaryTree leftSubtree,BinaryTree rightSubtree) { root = new BinaryTreeNode(element); count = 1; if(leftSubtree != null) { count = count + leftSubtree.size(); root.left = leftSubtree.root; } else root.left = null; if(rightSubtree != null) { count = count + rightSubtree.size(); root.right = rightSubtree.root; } else root.right = null; }
主要来看一下遍历的实现,把遍历写成一个迭代器(在链表里写了很多代码,感觉很憋屈,很多地方都花在遍历和迭代上,就是因为没有去实现Iterator)
在遍历中,要用到队列,先来看下队列迭代器是怎么实现的:
在前面写的队列LinkedQueue中,添加一个返回值为Iterator的方法:
public Iterator iterator(){ return new LinkedQueueIterator(front,rear,count); }
它实际上是返回另一个继承了Iterator类的类的对象,这个对象的构造函数一般来说是由LinkedQueue里的成员变量组成的(因为要实现Iterator里面的方法):
package Queue; import java.util.Iterator; import Bag.LinearNode; public class LinkedQueueIterator implements Iterator { private LinearNode front,rear,current; private int count; //迭代器类的构造器 public LinkedQueueIterator(LinearNode front,LinearNode rear,int count) { this.front = front; this.rear = rear; this.count = count; this.current = front; } public boolean hasNext() { return (current != null); } public Object next() { Object result = current.getElement(); current = current.getNext(); return result; } public void remove() { } }
上面说明了怎么去实现一个数据结构的迭代器,关键在于去实现特定于自身数据结构的Iterator方法(hasNext,next,remove)
在树的遍历中,需要借助于队列的迭代器,来返回一个树的迭代器,将树中元素按照遍历规则入队,最后返回队列的迭代器,这个迭代器就是树的迭代器。
中序遍历迭代器的实现(前序后序类似):借助于一个private的支持方法来将树中元素按序进队:
public Iterator iteratorInorder() { LinkedQueue queue = new LinkedQueue(); inorder(root,queue);//将以root为根的树按序进队 return queue.iterator();//返回队列的迭代器 } private void inorder(BinaryTreeNode node,LinkedQueue queue){ if(node != null) { inorder(node.left,queue); queue.enqueue(node.element); inorder(node.right,queue); } }
将遍历写成迭代迭代器会有利于很多后序操作,当然,也可以直接写一个遍历输出元素:
//直接写一个遍历的方法,不用迭代器也行 //public static void previsit(BinaryTreeNode node){ //if(node != null) //{ //System.out.println(node.element); //previsit(node.left); //previsit(node.right); //} //}
其他操作参见注释,不再分析实现,清单代码:
package Tree;
import java.util.Iterator;
import Queue.LinkedQueue;
public class BinaryTree implements BinaryTreeADT {
private int count; protected BinaryTreeNode root; //3个构造方法 public BinaryTree() { root = null; count = 0; } public BinaryTree(Object element) { root = new BinaryTreeNode(element); count = 1; } public BinaryTree(Object element,BinaryTree leftSubtree,BinaryTree rightSubtree) { root = new BinaryTreeNode(element); count = 1; if(leftSubtree != null) { count = count + leftSubtree.size(); root.left = leftSubtree.root; } else root.left = null; if(rightSubtree != null) { count = count + rightSubtree.size(); root.right = rightSubtree.root; } else root.right = null; }//接口定义的操作
public int size() {
return count;
}
public boolean isEmpty() {
return (count == 0);
}
public void removeLeftSubtree() {
if(root.left != null)
count = count - 1 - root.left.numChildren();
root.left = null;
}
public void removeRightSubtree() {
if(root.right != null)
count = count - 1 - root.right.numChildren();
root.right = null;
}
public Object find(Object target) {
Iterator it = this.iteratorInorder();
Object result = null;
while(it.hasNext())
{
result = it.next();
if(result.equals(target))
break;
else result = null;
}
return result;
}
public boolean contains(Object element) {
if(find(element) != null)
return true;
return false;
}
public Iterator iteratorInorder() { LinkedQueue queue = new LinkedQueue(); inorder(root,queue);//将以root为根的树按序进队 return queue.iterator();//返回队列的迭代器 } private void inorder(BinaryTreeNode node,LinkedQueue queue){ if(node != null) { inorder(node.left,queue); queue.enqueue(node.element); inorder(node.right,queue); } }
public Iterator PreInorder() {
LinkedQueue queue = new LinkedQueue();
preorder(root,queue);
return queue.iterator();
}
private void preorder(BinaryTreeNode node,LinkedQueue queue){
if(node != null)
{
queue.enqueue(node.element);
preorder(node.left,queue);
preorder(node.right,queue);
}
}
public Iterator PostInorder() {
LinkedQueue queue = new LinkedQueue();
postorder(root,queue);
return queue.iterator();
}
private void postorder(BinaryTreeNode node,LinkedQueue queue){
if(node != null)
{
postorder(node.left,queue);
postorder(node.right,queue);
queue.enqueue(node.element);
}
}
//直接写一个遍历的方法,不用迭代器也行 //public static void previsit(BinaryTreeNode node){ //if(node != null) //{ //System.out.println(node.element); //previsit(node.left); //previsit(node.right); //} //}
public static void main(String[] args) {
BinaryTree tree3 = new BinaryTree (3);
BinaryTree tree4 = new BinaryTree (4);
BinaryTree tree2 = new BinaryTree(2,tree3,tree4);
BinaryTree tree7 = new BinaryTree (7);
BinaryTree tree6 = new BinaryTree (6,tree7,null);
BinaryTree tree5 = new BinaryTree (5,null,tree6);
BinaryTree tree1 = new BinaryTree (1,tree2,tree5);
System.out.println("树的大小是: " + tree1.size());
System.out.println("树为空吗?: " + tree1.isEmpty());
//previsit(tree1.root);
System.out.println("\n中序遍历结果为: ");
Iterator it = tree1.iteratorInorder();
while(it.hasNext())
System.out.print(it.next() + " ");
System.out.println("\n前序遍历结果为: ");
it = tree1.PreInorder();
while(it.hasNext())
System.out.print(it.next() + " ");
System.out.println("\n后序遍历结果为: ");
it = tree1.PostInorder();
while(it.hasNext())
System.out.print(it.next() + " ");
System.out.println("\n\n" + tree1.find(0));
System.out.println("包含元素6吗?: " + tree1.contains(6));
System.out.println("包含元素8吗?: " + tree1.contains(8));
tree1.removeLeftSubtree();
System.out.println("\n删除左子树后中序遍历结果为: ");
it = tree1.iteratorInorder();
while(it.hasNext())
System.out.print(it.next() + " ");
}
}
你会发现,并没有去实现add和delete操作,因为在具体的应用需求之前,并不知道该怎么去添加和删除,它不像线性结构,添加和删除后是要调整树的形状的。
由于没有写一个addleft,addright方法,构造一个树来测试显得很冗长,在main方法前面好多行,构造了下面的二叉树:
结果如下:
树的大小是: 7
树为空吗?: false
中序遍历结果为:
3 2 4 1 5 7 6
前序遍历结果为:
1 2 3 4 5 6 7
后序遍历结果为:
3 4 2 7 6 5 1
null
包含元素6吗?: true
包含元素8吗?: false
删除左子树后中序遍历结果为:
1 5 7 6
相关文章推荐
- 数据结构——二叉树的链式实现(C语言)
- 二叉树的简介及链式结构实现
- 二叉树链式结构C代码实现
- 二叉树顺序结构实现/链式结构实现
- 二叉树的链式结构递归遍历实现
- 二叉树的链式存储结构 C++代码实现
- 二叉树的链式结构实现
- 大话数据结构 code 第6章 02二叉树链式结构实现_BiTreeLink
- 数据结构之C/C++实现二叉树的链式存储
- 大话数据结构 code 第五章 02二叉树链式结构实现_BiTreeLink
- 二叉树的链式存储结构 前序 后序 中序 层序遍历操作实现 判断是否完全二叉树
- 二叉树链式结构实现
- 【数据结构】二叉树链式结构实现_BiTreeLink
- 数据结构C语言实现之二叉树链式结构
- 二叉树的链式实现
- 线性表的链式存储结构之单链表结点类的实现_Java
- 用C语言实现简单链式队列结构
- 线性表的链式存储结构之单链表类的实现之补充_Java
- 数据结构(六)——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 二叉搜索树-链式结构实现方式