二叉树的定义: 树中结点度数不大于2的有序树
特性:
设当前结点序号(层序)为i
左孩子:i * 2 + 1;
右孩子:i * 2 + 2;
先序|中序, 先序|后序, 中序|后序, 层序|中序可以确定一个二叉树
结点
设计思路:
1.具备元素:数据域,左指针域,右指针域
通过左右指针(引用)将一颗树的结点进行连接
2.基本方法:类的构造方法和元素的set和get方法
public class TreeNode<E> {
/**
* data 节点元素值
* lChild 左孩子
* rChild 右孩子
*/
private E data;
private TreeNode<E> lChild;
private TreeNode<E> rChild;
public TreeNode() {
}
public TreeNode(E e) {
this.data = e;
}
public TreeNode(E data, TreeNode<E> lChild, TreeNode<E> rChild) {
this.data = data;
this.lChild = lChild;
this.rChild = rChild;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public TreeNode<E> getLChild() {
return lChild;
}
public void setLChild(TreeNode<E> lChild) {
this.lChild = lChild;
}
public TreeNode<E> getRChild() {
return rChild;
}
public void setRChild(TreeNode<E> rChild) {
this.rChild = rChild;
}
}
接口:
设计思路:关于接口设计我觉得应该简洁,所以只包含一棵树的应有的基本方法
1.创建方法
2.插入方法
3.删除方法
4.求高度
5.求节点数
public interface BinaryTree<E> {
/**
* @param val 根节点
* @param l 左子树
* @param r 右子树
* @Desription 手动建树
*/
void create(E val, TreeNode<E> l, TreeNode<E> r);
/**
* @param array
* @return TreeNode<E>
* @Desription 自动将数组转化成完全二叉树
*/
public TreeNode<E> buildTree(E[] array);
/**
* @param val
* @param p
* @Desription 将元素插入p的左结点,原先的左子树成为新结点的左子树
*/
void insertL(E val, TreeNode<E> p);
/**
* @param val
* @param p
* @Desription 将元素插入p的右节点,原先的右子树成为新节点的右子树
*/
void insertR(E val, TreeNode<E> p);
/**
* @param p
* @return TreeNode<E>
* @Desription 删除p的左子树
*/
TreeNode<E> deleteL(TreeNode<E> p);
/**
* @param p
* @return TreeNode<E>
* @Desription 删除p的右子树
*/
TreeNode<E> deleteR(TreeNode<E> p);
/**
* @param root
* @param value
* @return TreeNode<E>
* @Desription 在root中查找值为value的结点
*/
TreeNode<E> search(TreeNode<E> root, E value);
/**
* @param p
* @return boolean
* @Desription 判断是否是叶子结点
*/
boolean isLeaf(TreeNode<E> p);
/**
* @param p
* @return int
* @Desription 求树的高度
*/
int height(TreeNode<E> p);
/**
* @param p
* @return int
* @Desription 求结点数
*/
int size(TreeNode<E> p);
}
实现类:
设计思路:基于实现接口的的基础上实现了如下方法
-
4种遍历方式 先 中 后 层
-
对一些递归结构进行优化,一般来说,相同的问题用递归和递推求解,在最坏的看似复杂度相同都是O(n),但是常系数还是不同的。
递归:实质上是使用了系统栈来进行遍历,在最坏情况下可能需要递归n层
递推:实质上也是用栈来进行遍历的,在最坏情况下可能有n个点入栈出栈
public class LinkBinaryTree<E> implements BinaryTree<E>{
private TreeNode<E> root;
private List<TreeNode<E>> nodeList = null;
public LinkBinaryTree(){
root = null;
}
public LinkBinaryTree(E val){
this(val, null, null);
}
public LinkBinaryTree(E val, TreeNode<E> lp, TreeNode<E> rp){
TreeNode<E> p = new TreeNode<E>(val, lp, rp);
root = p;
}
public TreeNode<E> getRoot(){
return root;
}
public boolean isEmpty(){
return root == null;
}
@Override
public void create(E val, TreeNode<E> l, TreeNode<E> r) {
TreeNode<E> p = new TreeNode<>(val, l, r);
root = p;
}
@Override
public TreeNode<E> buildTree(E[] array) {
nodeList = new LinkedList<>();
for(int i = 0 ; i < array.length; i++){
nodeList.add(new TreeNode(array[i]));
}
for(int i = 0; i < array.length; i++){
nodeList.get(i).setLChild(nodeList.get(i * 2 + 1));
nodeList.get(i).setRChild(nodeList.get(i * 2 + 2));
}
//特判,最后一个父节点可能没有右孩子
int index = array.length / 2 - 1;
nodeList.get(index).setLChild(nodeList.get(index * 2 + 1));
if(array.length % 2 == 0){
nodeList.get(index).setRChild(nodeList.get(index * 2 + 2));
}
root = nodeList.get(0);
return root;
}
@Override
public void insertL(E val, TreeNode<E> p) {
TreeNode<E> newNode = new TreeNode<E>(val);
TreeNode<E> oldLChild = p.getLChild();
p.setLChild(newNode);
newNode.setLChild(oldLChild);
}
@Override
public void insertR(E val, TreeNode<E> p) {
TreeNode<E> newNode = new TreeNode<>(val);
TreeNode<E> oldRChild = p.getRChild();
p.setRChild(newNode);
newNode.setRChild(oldRChild);
}
@Override
public TreeNode<E> deleteL(TreeNode<E> p) {
if(p == null){
return null;
}else{
TreeNode<E> lChild = p.getLChild();
p.setLChild(null);
return lChild;
}
}
@Override
public TreeNode<E> deleteR(TreeNode<E> p) {
if(p == null){
return null;
}else {
TreeNode<E> rChild = p.getRChild();
p.setRChild(null);
return rChild;
}
}
@Override
public TreeNode<E> search(TreeNode<E> root, E value) {
LinkedList<TreeNode<E>> q = new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
TreeNode<E> treeNode = q.poll();
if(treeNode.getLChild() != null){
q.add(treeNode.getLChild());
}
if(treeNode.getRChild() != null){
q.add(treeNode.getRChild());
}
if(treeNode.getData() == value){
return treeNode;
}
}
return null;
}
@Override
public boolean isLeaf(TreeNode<E> p) {
if(p == null){
return false;
}
LinkedList<TreeNode<E>> q = new LinkedList<>();
q.add(p);
while(q.isEmpty()){
TreeNode<E> treeNode = q.poll();
if(treeNode.getLChild() != null){
q.add(treeNode.getLChild());
}
if(treeNode.getRChild() != null){
q.add(treeNode.getRChild());
}
if(treeNode.getData().equals(p.getData()) && treeNode.getLChild() == null && treeNode.getRChild() == null){
return true;
}
}
return false;
}
@Override
public int height(TreeNode<E> p) {
if(p == null){
return 0;
}else{
int i = height(p.getLChild()) + 1;
int j = height(p.getRChild()) + 1;
return Math.max(i, j);
}
}
@Override
public int size(TreeNode<E> p) {
if(p == null){
return 0;
}else{
return size(p.getLChild()) + size(p.getRChild()) + 1;
}
}
public void preOrder(TreeNode<E> p){
if(p != null){
System.out.print(p.getData() + " ");
preOrder(p.getLChild());
preOrder(p.getRChild());
}
}
public void nonRecPreOrder(TreeNode<E> p){
if(p != null){
Stack<TreeNode<E>> stack = new Stack<>();
TreeNode<E> treeNode = p;
while(treeNode != null || !stack.isEmpty()){
//存在左结点,则将左结点入栈
if(treeNode != null){
stack.push(treeNode);
System.out.print(stack.peek().getData() + " ");
treeNode = treeNode.getLChild();
}else{
treeNode = stack.pop();
treeNode = treeNode.getRChild();
}
}
}
}
public void inOrder(TreeNode<E> p){
if(p != null){
inOrder(p.getLChild());
System.out.print(p.getData() + " ");
inOrder(p.getRChild());
}
}
public void nonRecInOrder(TreeNode<E> p){
if(p != null){
Stack<TreeNode<E>> stack = new Stack<>();
TreeNode<E> treeNode = p;
while(treeNode != null || !stack.isEmpty()){
if(treeNode != null){
stack.push(treeNode);
treeNode = treeNode.getLChild();
}else{
treeNode = stack.pop();
System.out.print(treeNode.getData() + " ");
treeNode = treeNode.getRChild();
}
}
}
}
public void postOrder(TreeNode<E> p){
if(p != null){
postOrder(p.getLChild());
postOrder(p.getRChild());
System.out.print(p.getData() + " ");
}
}
public void nonRecPostOrder(TreeNode<E> p){
if(p != null){
Stack<TreeNode<E>> stack = new Stack<>();
TreeNode<E> treeNode = p;
TreeNode<E> preNode = null;
while(treeNode != null || !stack.isEmpty()){
while(treeNode != null){
stack.push(treeNode);
treeNode = treeNode.getLChild();
}
treeNode = stack.peek();
if(treeNode.getRChild() == null || treeNode.getRChild() == preNode){
treeNode = stack.pop();
System.out.print(treeNode.getData() + " ");
preNode = treeNode;
treeNode = null;
}else{
treeNode = treeNode.getRChild();
}
}
}
}
public void levelOrder(TreeNode<E> p){
if(p != null){
LinkedList<TreeNode<E>> q = new LinkedList<>();
q.add(p);
while(!q.isEmpty()){
TreeNode<E> treeNode = q.poll();
System.out.print(treeNode.getData() + " ");
if(treeNode.getLChild() != null){
q.add(treeNode.getLChild());
}
if(treeNode.getRChild() != null){
q.add(treeNode.getRChild());
}
}
}
}
}
参考文章: