从这里始将要继续进行Java数据结构的相关讲解,Are you ready?Let's go~~

Java中的数据结构模型可以分为一下几部分:

1.线性结构

2.树形结构

3.图形或者网状结构

接下来的几章,我们将会分别讲解这几种数据结构,主要也是通过Java代码的方式来讲解相应的数据结构。

今天要讲解的是:Java线性结构

对于之前普通树和二叉树的讲解请参考地址:

今天我们将要进行的是Java树中的哈夫曼树(HaffmanTree),哈夫曼编码(HaffmanTreeCode),排序二叉树

和红黑树进行相应的讲解,由于内容比较多,请耐心学习,同时有不足的地方也欢迎批评指正。谢谢~~~

1.哈夫曼树的讲解

  哈夫曼树又称为最优二叉树,是一种带权路径最短的二叉树。哈夫曼树是二叉树的又一种应用,在信息检索中经常会使用到的。

下面还是简单的介绍一下哈夫曼树的基本特性,至于更详细的信息请自己百度哦。

节点之间的路径的长度:

从一个节点到另外一个节点的分支的数量,我们称之为两个节点之间的路径的长度。

树的路径长度:

从根节点到树中每个节点的路径的长度之和,我们称之树的路径的长度。

节点的带权路径的长度:

   从该节点到根节点之间路径的长度与节点权值的乘积

树的带权路径的长度:

   树中所有的节点的带权路径之和

带权路径最小的二叉树,我们称之为哈夫曼树或者为最优二叉树

对于具有n个叶子节点的二叉树,一共需要2*n-1个节点。

下面给出具体的代码来实现创建哈夫曼树的过程:

废话也不多说,如果感兴趣的话请仔细查看下面的代码哦。

package com.yonyou.test;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue; /**
* 测试类
* @author 小浩
* @创建日期 2015-3-20
*/
public class Test
{
public static void main(String[] args)
{
List<HuffmanTree.Node<String>> nodes = new ArrayList<HuffmanTree.Node<String>>();
nodes.add(new HuffmanTree.Node<String>("A" , 40.0));
nodes.add(new HuffmanTree.Node<String>("B" , 7.0));
nodes.add(new HuffmanTree.Node<String>("C" , 10.0));
nodes.add(new HuffmanTree.Node<String>("D" , 30.0));
nodes.add(new HuffmanTree.Node<String>("E" , 12.0));
nodes.add(new HuffmanTree.Node<String>("F" , 2.0));
HuffmanTree.Node<String> root = HuffmanTree.createTree(nodes);
System.out.println(HuffmanTree.breadthFirst(root));
}
} /**
* 创建哈夫曼树的过程
* @author 小浩
* @创建日期 2015-3-23
* @param <E>
*/
class HuffmanTree
{
public static class Node<E>
{
//节点中存储的数据
E data;
//当前节点所对应的权值
double weight;
//当前节点的左节点
Node<E> leftChild;
//当前节点的右节点
Node<E> rightChild;
public Node(E data , double weight)
{
this.data = data;
this.weight = weight;
}
public String toString()
{
return "Node[data=" + data
+ ", weight=" + weight + "]";
}
} /**
* 构造哈夫曼树
* @param nodes 节点集合
* @return 构造出来的哈夫曼树的根节点
*/
public static <E> Node<E> createTree(List<Node<E>> nodes)
{
// 只要nodes数组中还有2个以上的节点
while (nodes.size() > 1)
{
//快速排序,对当前节点进行快排操作...
quickSort(nodes);
// 获取权值最小的两个节点
Node<E> left = nodes.get(nodes.size() - 1);
Node<E> right = nodes.get(nodes.size() - 2);
// 生成新节点,新节点的权值为两个子节点的权值之和
Node<E> parent = new Node<E>(null , left.weight + right.weight);
// 让新节点作为权值最小的两个节点的父节点
parent.leftChild = left;
parent.rightChild = right;
// 删除权值最小的两个节点
nodes.remove(nodes.size() - 1);
nodes.remove(nodes.size() - 1);
// 将新生成的父节点添加到集合中
nodes.add(parent);
}
// 返回nodes集合中唯一的节点,也就是根节点
return nodes.get(0);
} /**
* 将指定数组的i和j索引处的元素交换
* @param nodes
* @param i
* @param j
*/
private static <E> void swap(List<Node<E>> nodes, int i, int j)
{
Node<E> tmp;
tmp = nodes.get(i);
nodes.set(i , nodes.get(j));
nodes.set(j , tmp);
} /**
* 实现快速排序算法,用于对节点进行排序
* @param nodes
* @param start
* @param end
*/
private static <E> void subSort(List<Node<E>> nodes
, int start , int end)
{
// 需要排序
if (start < end)
{
// 以第一个元素作为分界值
Node base = nodes.get(start);
// i从左边搜索,搜索大于分界值的元素的索引
int i = start;
// j从右边开始搜索,搜索小于分界值的元素的索引
int j = end + 1;
while(true)
{
// 找到大于分界值的元素的索引,或i已经到了end处
while(i < end && nodes.get(++i).weight >= base.weight);
// 找到小于分界值的元素的索引,或j已经到了start处
while(j > start && nodes.get(--j).weight <= base.weight);
if (i < j)
{
swap(nodes , i , j);
}
else
{
break;
}
}
swap(nodes , start , j);
// 递归左子序列
subSort(nodes , start , j - 1);
// 递归右边子序列
subSort(nodes , j + 1, end);
}
} /**
* 快速排序
* @param nodes
*/
public static <E> void quickSort(List<Node<E>> nodes)
{
subSort(nodes , 0 , nodes.size() - 1);
} /**
* 广度优先遍历
* @param root
* @return
*/
public static List<Node> breadthFirst(Node root)
{
Queue<Node> queue = new ArrayDeque<Node>();
List<Node> list = new ArrayList<Node>();
if( root != null)
{
// 将根元素入“队列”
queue.offer(root);
}
while(!queue.isEmpty())
{
// 将该队列的“队尾”的元素添加到List中
list.add(queue.peek());
Node p = queue.poll();
// 如果左子节点不为null,将它加入“队列”
if(p.leftChild != null)
{
queue.offer(p.leftChild);
}
// 如果右子节点不为null,将它加入“队列”
if(p.rightChild != null)
{
queue.offer(p.rightChild);
}
}
return list;
}
}

2.排序二叉树的讲解

  所谓排序二叉树:指的是给定一棵树,要么这棵树是一棵空树,要么这棵树具有以下特点:

1)、如果它的左子树不空,那么它的左子树上面的所有节点都小于根节点

2)、如果它的右子树不空,那么它的右子树上面的所有节点都大于根节点

3)、它的左、右子树也分别是一棵排序二叉树

具体的请看代码:

package com.yonyou.test;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue; /**
* 测试类
* @author 小浩
* @创建日期 2015-3-20
*/
public class Test
{
public static void main(String[] args)
{
}
} /**
* 创建排序二叉树的过程
* @author 小浩
* @创建日期 2015-3-23
* @param <E>
*/
class SortedBinTree<T extends Comparable>
{
/**
* 用于存储的节点的相关信息
* @author 小浩
* @创建日期 2015-3-23
*/
static class Node
{
Object data;
Node parent;
Node left;
Node right;
public Node(Object data , Node parent
, Node left , Node right)
{
this.data = data;
this.parent = parent;
this.left = left;
this.right = right;
}
public String toString()
{
return "[data=" + data + "]";
}
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj.getClass() == Node.class)
{
Node target = (Node)obj;
return data.equals(target.data)
&& left == target.left
&& right == target.right
&& parent == target.parent;
}
return false;
}
}
private Node root;
// 两个构造器用于创建排序二叉树
public SortedBinTree()
{
root = null;
}
public SortedBinTree(T o)
{
root = new Node(o , null , null , null);
} /**
* 添加节点
* @param ele
*/
@SuppressWarnings("unchecked")
public void add(T ele)
{
// 如果根节点为null
if (root == null)
{
root = new Node(ele , null , null , null);
}
else
{
Node current = root;
Node parent = null;
int cmp = 0;
// 搜索合适的叶子节点,以该叶子节点为父节点添加新节点
do
{
parent = current;
cmp = ele.compareTo(current.data);
// 如果新节点的值大于当前节点的值
if (cmp > 0)
{
// 以右子节点作为当前节点
current = current.right;
}
// 如果新节点的值小于当前节点的值
else
{
// 以左子节点作为当前节点
current = current.left;
}
}while (current != null);
// 创建新节点
Node newNode = new Node(ele , parent , null , null);
// 如果新节点的值大于父节点的值
if (cmp > 0)
{
// 新节点作为父节点的右子节点
parent.right = newNode;
}
// 如果新节点的值小于父节点的值
else
{
// 新节点作为父节点的左子节点
parent.left = newNode;
}
}
} /**
* 删除节点
* @param ele
*/
public void remove(T ele)
{
// 获取要删除的节点
Node target = getNode(ele);
// 如果要删除的节点为null,直接返回
if (target == null)
{
return;
}
// 如果要删除的节点的左、右子树为空
if (target.left == null
&& target.right == null)
{
// 如果要删除节点是根节点
if (target == root)
{
root = null;
}
else
{
// 要删除节点是父节点的左子节点
if (target == target.parent.left)
{
// 将target的父节点的left设为null
target.parent.left = null;
}
// 要删除节点是父节点的左子节点
else
{
// 将target的父节点的right设为null
target.parent.right = null;
}
target.parent = null;
}
}
// 如果要删除的节点只有右子树
else if (target.left == null
&& target.right != null)
{
// 如果要删除节点是根节点
if (target == root)
{
root = target.right;
}
else
{
// 如果要删除节点是父节点的左子节点
if (target == target.parent.left)
{
// 让target的父节点的left指向target的右子树
target.parent.left = target.right;
}
// 如果要删除节点是父节点的右子节点
else
{
// 让target的父节点的right指向target的右子树
target.parent.right = target.right;
}
//让target的右子树的parent指向target的parent
target.right.parent = target.parent;
}
}
// 如果要删除的节点只有左子树
else if(target.left != null
&& target.right == null)
{
// 被删除节点是根节点
if (target == root)
{
root = target.left;
}
else
{
// 被删除节点是父节点的左子节点
if (target == target.parent.left)
{
// 让target的父节点的left指向target的左子树
target.parent.left = target.left;
}
else
{
// 让target的父节点的right指向target的左子树
target.parent.right = target.left;
}
// 让target的左子树的parent指向target的parent
target.left.parent = target.parent;
}
}
// 如果要删除节点既有左子树,又有右子树
else
{
// leftMaxNode用于保存target节点的左子树中值最大的节点
Node leftMaxNode = target.left;
// 搜索target节点的左子树中值最大的节点
while (leftMaxNode.right != null)
{
leftMaxNode = leftMaxNode.right;
}
// 从原来的子树中删除leftMaxNode节点
leftMaxNode.parent.right = null;
// 让leftMaxNode的parent指向target的parent
leftMaxNode.parent = target.parent;
// 要删除节点是父节点的左子节点
if (target == target.parent.left)
{
// 让target的父节点的left指向leftMaxNode
target.parent.left = leftMaxNode;
}
// 要删除节点是父节点的右子节点
else
{
// 让target的父节点的right指向leftMaxNode
target.parent.right = leftMaxNode;
}
leftMaxNode.left = target.left;
leftMaxNode.right = target.right;
target.parent = target.left = target.right = null;
}
}
// 根据给定的值搜索节点
@SuppressWarnings("unchecked")
public Node getNode(T ele)
{
//从根节点开始搜索
Node p = root;
while (p != null)
{
int cmp = ele.compareTo(p.data);
// 如果搜索的值小于当前p节点的值
if (cmp < 0)
{
// 向左子树搜索
p = p.left;
}
// 如果搜索的值大于当前p节点的值
else if (cmp > 0)
{
// 向右子树搜索
p = p.right;
}
else
{
return p;
}
}
return null;
}
// 广度优先遍历
public List<Node> breadthFirst()
{
Queue<Node> queue = new ArrayDeque<Node>();
List<Node> list = new ArrayList<Node>();
if( root != null)
{
// 将根元素加入“队列”
queue.offer(root);
}
while(!queue.isEmpty())
{
// 将该队列的“队尾”的元素添加到List中
list.add(queue.peek());
Node p = queue.poll();
// 如果左子节点不为null,将它加入“队列”
if(p.left != null)
{
queue.offer(p.left);
}
// 如果右子节点不为null,将它加入“队列”
if(p.right != null)
{
queue.offer(p.right);
}
}
return list;
}
}

3、红黑树的讲解

 

public class RedBlackTree<T extends Comparable>
{
// 定义红黑树的颜色
private static final boolean RED = false;
private static final boolean BLACK = true;
static class Node
{
Object data;
Node parent;
Node left;
Node right;
// 节点的默认颜色是黑色
boolean color = BLACK;
public Node(Object data , Node parent
, Node left , Node right)
{
this.data = data;
this.parent = parent;
this.left = left;
this.right = right;
}
public String toString()
{
return "[data=" + data
+ ", color=" + color + "]";
}
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj.getClass() == Node.class)
{
Node target = (Node)obj;
return data.equals(target.data)
&& color == target.color
&& left == target.left
&& right == target.right
&& parent == target.parent;
}
return false;
}
}
private Node root;
// 两个构造器用于创建排序二叉树
public RedBlackTree()
{
root = null;
}
public RedBlackTree(T o)
{
root = new Node(o , null , null , null);
}
// 添加节点
public void add(T ele)
{
// 如果根节点为null
if (root == null)
{
root = new Node(ele , null , null , null);
}
else
{
Node current = root;
Node parent = null;
int cmp = 0;
// 搜索合适的叶子节点,以该叶子节点为父节点添加新节点
do
{
parent = current;
cmp = ele.compareTo(current.data);
// 如果新节点的值大于当前节点的值
if (cmp > 0)
{
// 以右子节点作为当前节点
current = current.right;
}
// 如果新节点的值小于当前节点的值
else
{
// 以左子节点作为当前节点
current = current.left;
}
}
while (current != null);
// 创建新节点
Node newNode = new Node(ele , parent , null , null);
// 如果新节点的值大于父节点的值
if (cmp > 0)
{
// 新节点作为父节点的右子节点
parent.right = newNode;
}
// 如果新节点的值小于父节点的值
else
{
//新节点作为父节点的左子节点
parent.left = newNode;
}
// 维护红黑树
fixAfterInsertion(newNode);
}
}
// 删除节点
public void remove(T ele)
{
// 获取要删除的节点
Node target = getNode(ele);
// 如果要删除节点的左子树、右子树都不为空
if (target.left != null && target.right != null)
{
// 找到target节点中序遍历的前一个节点
// s用于保存target节点的左子树中值最大的节点
Node s = target.left;
// 搜索target节点的左子树中值最大的节点
while (s.right != null)
{
s = s.right;
}
// 用s节点来代替p节点
target.data = s.data;
target = s;
}
// 开始修复它的替换节点,如果该替换节点不为null
Node replacement = (target.left != null ?
target.left : target.right);
if (replacement != null)
{
// 让replacement的parent指向target的parent
replacement.parent = target.parent;
// 如果target的parent为null,表明target本身是根节点
if (target.parent == null)
{
root = replacement;
}
// 如果target是其父节点的左子节点
else if (target == target.parent.left)
{
// 让target的父节点left指向replacement
target.parent.left = replacement;
}
// 如果target是其父节点的右子节点
else
{
// 让target的父节点right指向replacement
target.parent.right = replacement;
}
// 彻底删除target节点
target.left = target.right = target.parent = null; // 修复红黑树
if (target.color == BLACK)
{
fixAfterDeletion(replacement);
}
}
// target本身是根节点
else if (target.parent == null)
{
root = null;
}
else
{
// target没有子节点,把它当成虚的替换节点。
// 修复红黑树
if (target.color == BLACK)
{
fixAfterDeletion(target);
}
if (target.parent != null)
{
// 如果target是其父节点的左子节点
if (target == target.parent.left)
{
// 将target的父节点left设为null
target.parent.left = null;
}
// 如果target是其父节点的右子节点
else if (target == target.parent.right)
{
// 将target的父节点right设为null
target.parent.right = null;
}
// 将target的parent设置null
target.parent = null;
}
}
}
// 根据给定的值搜索节点
public Node getNode(T ele)
{
// 从根节点开始搜索
Node p = root;
while (p != null)
{
int cmp = ele.compareTo(p.data);
// 如果搜索的值小于当前p节点的值
if (cmp < 0)
{
// 向左子树搜索
p = p.left;
}
// 如果搜索的值大于当前p节点的值
else if (cmp > 0)
{
// 向右子树搜索
p = p.right;
}
else
{
return p;
}
}
return null;
}
// 广度优先遍历
public List<Node> breadthFirst()
{
Queue<Node> queue = new ArrayDeque<Node>();
List<Node> list = new ArrayList<Node>();
if( root != null)
{
// 将根元素入“队列”
queue.offer(root);
}
while(!queue.isEmpty())
{
// 将该队列的“队尾”的元素添加到List中
list.add(queue.peek());
Node p = queue.poll();
// 如果左子节点不为null,将它入“队列”
if(p.left != null)
{
queue.offer(p.left);
}
// 如果右子节点不为null,将它入“队列”
if(p.right != null)
{
queue.offer(p.right);
}
}
return list;
}
// 插入节点后修复红黑树
private void fixAfterInsertion(Node x)
{
x.color = RED;
// 直到x节点的父节点不是根,且x的父节点不是红色
while (x != null && x != root
&& x.parent.color == RED)
{
// 如果x的父节点是其父节点的左子节点
if (parentOf(x) == leftOf(parentOf(parentOf(x))))
{
// 获取x的父节点的兄弟节点
Node y = rightOf(parentOf(parentOf(x)));
// 如果x的父节点的兄弟节点是红色
if (colorOf(y) == RED)
{
// 将x的父节点设为黑色
setColor(parentOf(x), BLACK);
// 将x的父节点的兄弟节点设为黑色
setColor(y, BLACK);
// 将x的父节点的父节点设为红色
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
}
// 如果x的父节点的兄弟节点是黑色
else
{
// 如果x是其父节点的右子节点
if (x == rightOf(parentOf(x)))
{
// 将x的父节点设为x
x = parentOf(x);
rotateLeft(x);
}
// 把x的父节点设为黑色
setColor(parentOf(x), BLACK);
// 把x的父节点的父节点设为红色
setColor(parentOf(parentOf(x)), RED);
rotateRight(parentOf(parentOf(x)));
}
}
// 如果x的父节点是其父节点的右子节点
else
{
// 获取x的父节点的兄弟节点
Node y = leftOf(parentOf(parentOf(x)));
// 如果x的父节点的兄弟节点是红色
if (colorOf(y) == RED)
{
// 将x的父节点设为黑色。
setColor(parentOf(x), BLACK);
// 将x的父节点的兄弟节点设为黑色
setColor(y, BLACK);
// 将x的父节点的父节点设为红色
setColor(parentOf(parentOf(x)), RED);
// 将x设为x的父节点的节点
x = parentOf(parentOf(x));
}
// 如果x的父节点的兄弟节点是黑色
else
{
// 如果x是其父节点的左子节点
if (x == leftOf(parentOf(x)))
{
//将x的父节点设为x
x = parentOf(x);
rotateRight(x);
}
// 把x的父节点设为黑色
setColor(parentOf(x), BLACK);
// 把x的父节点的父节点设为红色
setColor(parentOf(parentOf(x)), RED);
rotateLeft(parentOf(parentOf(x)));
}
}
}
// 将根节点设为黑色
root.color = BLACK;
}
// 删除节点后修复红黑树
private void fixAfterDeletion(Node x)
{
// 直到x不是根节点,且x的颜色是黑色
while (x != root && colorOf(x) == BLACK)
{
// 如果x是其父节点的左子节点
if (x == leftOf(parentOf(x)))
{
// 获取x节点的兄弟节点
Node sib = rightOf(parentOf(x));
// 如果sib节点是红色
if (colorOf(sib) == RED)
{
// 将sib节点设为黑色
setColor(sib, BLACK);
// 将x的父节点设为红色
setColor(parentOf(x), RED);
rotateLeft(parentOf(x));
// 再次将sib设为x的父节点的右子节点
sib = rightOf(parentOf(x));
}
// 如果sib的两个子节点都是黑色
if (colorOf(leftOf(sib)) == BLACK
&& colorOf(rightOf(sib)) == BLACK)
{
// 将sib设为红色
setColor(sib, RED);
// 让x等于x的父节点
x = parentOf(x);
}
else
{
// 如果sib的只有右子节点是黑色
if (colorOf(rightOf(sib)) == BLACK)
{
// 将sib的左子节点也设为黑色
setColor(leftOf(sib), BLACK);
// 将sib设为红色
setColor(sib, RED);
rotateRight(sib);
sib = rightOf(parentOf(x));
}
// 设置sib的颜色与x的父节点的颜色相同
setColor(sib, colorOf(parentOf(x)));
// 将x的父节点设为黑色
setColor(parentOf(x), BLACK);
// 将sib的右子节点设为黑色
setColor(rightOf(sib), BLACK);
rotateLeft(parentOf(x));
x = root;
}
}
// 如果x是其父节点的右子节点
else
{
// 获取x节点的兄弟节点
Node sib = leftOf(parentOf(x));
// 如果sib的颜色是红色
if (colorOf(sib) == RED)
{
// 将sib的颜色设为黑色
setColor(sib, BLACK);
// 将sib的父节点设为红色
setColor(parentOf(x), RED);
rotateRight(parentOf(x));
sib = leftOf(parentOf(x));
}
// 如果sib的两个子节点都是黑色
if (colorOf(rightOf(sib)) == BLACK
&& colorOf(leftOf(sib)) == BLACK)
{
// 将sib设为红色
setColor(sib, RED);
//让x等于x的父节点
x = parentOf(x);
}
else
{
// 如果sib只有左子节点是黑色
if (colorOf(leftOf(sib)) == BLACK)
{
// 将sib的右子节点也设为黑色
setColor(rightOf(sib), BLACK);
// 将sib设为红色
setColor(sib, RED);
rotateLeft(sib);
sib = leftOf(parentOf(x));
}
// 将sib的颜色设为与x的父节点颜色相同
setColor(sib, colorOf(parentOf(x)));
// 将x的父节点设为黑色
setColor(parentOf(x), BLACK);
// 将sib的左子节点设为黑色
setColor(leftOf(sib), BLACK);
rotateRight(parentOf(x));
x = root;
}
}
}
setColor(x, BLACK);
}
// 获取指定节点的颜色
private boolean colorOf(Node p)
{
return (p == null ? BLACK : p.color);
}
// 获取指定节点的父节点
private Node parentOf(Node p)
{
return (p == null ? null: p.parent);
}
// 为指定节点设置颜色
private void setColor(Node p, boolean c)
{
if (p != null)
{
p.color = c;
}
}
// 获取指定节点的左子节点
private Node leftOf(Node p)
{
return (p == null) ? null: p.left;
}
// 获取指定节点的右子节点
private Node rightOf(Node p)
{
return (p == null) ? null: p.right;
}
/**
* 执行如下转换
* p r
* r p
* q q
*/
private void rotateLeft(Node p)
{
if (p != null)
{
// 取得p的右子节点
Node r = p.right;
Node q = r.left;
// 将r的左子节点链到p的右节点链上
p.right = q;
// 让r的左子节点的parent指向p节点
if (q != null)
{
q.parent = p;
}
r.parent = p.parent;
// 如果p已经是根节点
if (p.parent == null)
{
root = r;
}
// 如果p是其父节点的左子节点
else if (p.parent.left == p)
{
// 将r设为p的父节点的左子节点
p.parent.left = r;
}
else
{
// 将r设为p的父节点的右子节点
p.parent.right = r;
}
r.left = p;
p.parent = r;
}
}
/**
* 执行如下转换
* p l
* l p
* q q
*/
private void rotateRight(Node p)
{
if (p != null)
{
// 取得p的左子节点
Node l = p.left;
Node q = l.right;
// 将l的右子节点链到p的左节点链上
p.left = q;
// 让l的右子节点的parent指向p节点
if (q != null)
{
q.parent = p;
}
l.parent = p.parent;
// 如果p已经是根节点
if (p.parent == null)
{
root = l;
}
// 如果p是其父节点的右子节点
else if (p.parent.right == p)
{
// 将l设为p的父节点的右子节点
p.parent.right = l;
}
else
{
// 将l设为p的父节点的左子节点
p.parent.left = l;
}
l.right = p;
p.parent = l;
}
}
// 实现中序遍历
public List<Node> inIterator()
{
return inIterator(root);
}
private List<Node> inIterator(Node node)
{
List<Node> list = new ArrayList<Node>();
// 递归处理左子树
if (node.left != null)
{
list.addAll(inIterator(node.left));
}
// 处理根节点
list.add(node);
// 递归处理右子树
if (node.right != null)
{
list.addAll(inIterator(node.right));
}
return list;
}
}

  

 

  

Java数据结构之树和二叉树(2)的更多相关文章

  1. Java数据结构之树和二叉树

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  2. python数据结构之树和二叉树(先序遍历、中序遍历和后序遍历)

    python数据结构之树和二叉树(先序遍历.中序遍历和后序遍历) 树 树是\(n\)(\(n\ge 0\))个结点的有限集.在任意一棵非空树中,有且只有一个根结点. 二叉树是有限个元素的集合,该集合或 ...

  3. Java数据结构和算法(六)--二叉树

    什么是树? 上面图例就是一个树,用圆代表节点,连接圆的直线代表边.树的顶端总有一个节点,通过它连接第二层的节点,然后第二层连向更下一层的节点,以此递推 ,所以树的顶端小,底部大.和现实中的树是相反的, ...

  4. java数据结构之树

    树定义和基本术语定义树(Tree)是n(n≥0)个结点的有限集T,并且当n>0时满足下列条件:     (1)有且仅有一个特定的称为根(Root)的结点:     (2)当n>1时,其余结 ...

  5. 【PHP数据结构】树和二叉树

    树的概念其实非常地广泛,也非常地常见,大家见到这个词千万不要惊慌,因为真的每天你都能见到树结构在我们生活中的应用.比如说公司的组织结构: 另外像我们家里的族谱,或者说是我们的家庭结构,也是一个典型的树 ...

  6. java数据结构-12树相关概念

    一.树 1.概念: 包含n(n>=0)个结点的有穷集:树有多个节点(node),用以储存元素.某些节点之间存在一定的关系,用连线表示,连线称为边(edge).边的上端节点称为父节点,下端称为子节 ...

  7. 【Java】 大话数据结构(9) 树(二叉树、线索二叉树)

    本文根据<大话数据结构>一书,对Java版的二叉树.线索二叉树进行了一定程度的实现. 另: 二叉排序树(二叉搜索树) 平衡二叉树(AVL树) 二叉树的性质 性质1:二叉树第i层上的结点数目 ...

  8. Java数据结构——AVL树

    AVL树(平衡二叉树)定义 AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,并且拥有自平衡机制.在AV ...

  9. python数据结构之树(二叉树的遍历)

    树是数据结构中非常重要的一种,主要的用途是用来提高查找效率,对于要重复查找的情况效果更佳,如二叉排序树.FP-树. 本篇学习笔记来自:二叉树及其七种遍历方式.python遍历与非遍历方式实现二叉树 介 ...

随机推荐

  1. Yii系列教程(二):功能简介

    1 MVC架构 1.1处理流程 一个Web请求在Yii内部的执行流程如下图所示: 1.2组件角色 组件名 角色与责任 index.php 入口脚本.创建Application的单例对象. applic ...

  2. hdu 1850 Being a Good Boy in Spring Festival(Nimm Game)

    题意:Nimm Game 思路:Nimm Game #include<iostream> #include<stdio.h> using namespace std; int ...

  3. 【LeetCode】169 - Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  4. winform form

    WinForm:Windows Form,.Net中用来开发Windows窗口程序的技术,无论是之前学的控制台程序,还是后面要学的asp.net都是调用.net框架,因此所有知识点都是一样的.新建一个 ...

  5. failback 和failover

    dubbo 和motan都有在注册中心中都有这个概念 Failover 失效转移通俗地说,即当A无法为客户服务时,系统能够自动地切换,使B能够及时地顶上继续为客户提供服务,且客户感觉不到这个为他提供服 ...

  6. [转]Python文件操作

    前言 这里的“文件”不单单指磁盘上的普通文件,也指代任何抽象层面上的文件.例如:通过URL打开一个Web页面“文件”,Unix系统下进程间通讯也是通过抽象的进程“文件”进行的.由于使用了统一的接口,从 ...

  7. bzoj3717: [PA2014]Pakowanie

    Time Limit: 90 Sec Memory Limit: 256 MBSubmit: 128 Solved: 43[Submit][Status][Discuss]Description 你有 ...

  8. 一个采用python获取股票数据的开源库,相当全,及一些量化投资策略库

    tushare: http://tushare.waditu.com/index.html 为什么是Python? 就跟javascript在web领域无可撼动的地位一样,Python也已经在金融量化 ...

  9. ubuntu14.04恢复系统默认中文字体

    今天 Ubuntu14.04已发布就进行了更新,在配置过程中,无意安装了某些中文字体,导致系统的中文字体极其难看,根据网上说的修改配置文件和tweak 修改的方法都不能解决,最终找到的解决办法(htt ...

  10. ACM之最短路径做题笔记与记录

    在这里纪念一下从4月开始一直因为事情而荒废了的最短路,多亏了jbb的帮助,我才完成了FZU热身赛一题简单的一个用模拟链表存边以及最短路径的学习,目前(6.5)已经学会使用了最简单的djstral与sp ...