您的位置:首页 > 其它

基于链表节点实现二叉树节点

2016-03-19 20:29 155 查看
package codes04;
/*
* 二叉树节点ADT接口
*/
public interface BinTreePosition extends Position{
// 判断是否有父节点
public boolean hasParent();
// 返回当前节点的父节点
public BinTreePosition getParent();
// 设置当前节点的父节点
public void setParent(BinTreePosition p);

// 判断是否为叶子节点
public boolean isLeaf();
// 判断是否为左孩子
public boolean isLChild();
// 判断是否有左孩子
public boolean hasLChild();
// 返回当前节点的左孩子
public BinTreePosition getLChild();
// 设置当前节点的左孩子 (this.lChild和c.parent都不一定为空)
public void setLChild(BinTreePosition c);

//判断是否为右孩子
public boolean isRChild();
// 判断是否有右孩子
public boolean hasRChild();
// 返回当前节点的右孩子
public BinTreePosition getRChild();
// 设置当前节点的右孩子,(注:this.rChild和c.parent都不一定为空)
public void setRChild(BinTreePosition c);

// 返回当前节点后代元素的数目
public int getSize();
// 在孩子发生变化后,更新当前节点及其祖先的规模
public void updateSize();

// 返回当前节点的高度
public int getHeight();
// 在孩子发生变化后,更新当前节点及其祖先的高度
public void updateHeight();

// 返回当前节点的深度
public int getDepth();
// 在父亲发生变化后。更新当前节点及其后代的深度
public void updateDepth();

// 按照中序遍历的次序,找到当前节点的直接前驱
public BinTreePosition getPrev();

// 按照中序遍历的次序,找到当前节点的直接后继
public BinTreePosition getSucc();

// 断绝当前节点与其父亲的父子关系,返回当前节点
public BinTreePosition secede();

// 将节点c作为当前节点的左孩子
public BinTreePosition attachL(BinTreePosition c);

// 将节点c作为当前节点的右孩子
public BinTreePosition attachR(BinTreePosition c);

// 前序遍历
public MyIterator elementsPreorder();

// 中序遍历
public MyIterator elementsInorder();

// 后序遍历
public MyIterator elementsPostorder();

// 层次遍历
public MyIterator elementsLevelorder();
}


package codes04;
/*
* 基于链表节点实现二叉树节点
*
*/
public class BinTreeNode implements BinTreePosition{
// 该节点中存放的对象
protected Object element;
// 父亲
protected BinTreePosition parent;
// 左孩子
protected BinTreePosition lChild;
// 右孩子
protected BinTreePosition rChild;
// 后代数目
protected int size;
// 高度
protected int height;
// 深度
protected int depth;

/**************************** 构造方法 ****************************/
public BinTreeNode(){
this(null, null, true, null, null);
}
public BinTreeNode(Object e, BinTreePosition p, boolean asLChild, BinTreePosition l, BinTreePosition r){
// e:节点内容, p:父节点, asLChild:是否作为父节点的左孩子,l:左孩子, r:右孩子
// 初始化
size = 1;
// 深度和高度都是从零开始的
height = depth = 0;
// 相当于设置根节点
parent = lChild = rChild = null;
// 存放的对象
element = e;
// 建立与父亲的关系
// 如果p不为null,则
if (null != p){
// 如果asLChild为true,则将该节点作为p节点的左孩子
if (asLChild) {
p.attachL(this);
}else{
// 如果asLChild为false,则将该节点作为p节点的右孩子
p.attachR(this);
}
}
// 建立与孩子的关系
if (null != l) {
// 如果l不为null,则将l作为该节点的左孩子
attachL(l);
}
if (null != r){
// 如果r不为null,则将r作为该节点的右孩子
attachR(r);
}
}

/**************************** Position接口方法 ********************************/
// 返回当前节点中存放的对象
public Object getElem(){
return element;
}
// 将对象obj存入当前节点,并返回此前的内容
public Object setElem(Object obj){
Object bak = element;
element = obj;
return bak;
}

/**************************** BinTreePosition接口方法 *************************/
// 判断是否有父亲(为使代码描述简洁)
public boolean hasParent(){
return null != parent;
}
// 返回当前节点的父节点
public BinTreePosition getParent(){
return parent;
}
// 设置当前节点的父节点
public void setParent(BinTreePosition p){
parent = p;
}
// 判断是否为叶子
public boolean isLeaf(){
return !hasLChild() && !hasRChild();
}
// 判断是否为左孩子
public boolean isLChild(){
// 若当前节点有父亲,而且是左孩子,则返回true;否则,返回false
return (hasParent() && this == getParent().getLChild()) ? true : false;
}
// 判断是否有左孩子
public boolean hasLChild(){
return null != lChild;
}
// 返回当前节点的左孩子
public BinTreePosition getLChild(){
return lChild;
}
// 设置当前节点的左孩子(注意:this.lChild和c.parent都不一定为空)
public void setLChild(BinTreePosition c){
lChild = c;
}

// 判断是否为右孩子(为使代码描述简洁)
public boolean isRChild(){
// 若当前节点有父亲,而且是右孩子,则返回true;否则,返回false
return (hasParent() && this == getParent().getRChild()) ? true : false;
}
// 判断是否有右孩子(为使代码描述简洁)
public boolean hasRChild(){
return null != rChild;
}
// 返回当前节点的右孩子
public BinTreePosition getRChild(){
return rChild;
}
// 设置当前节点的右孩子(注意:this.rChild和c.parent都不一定为空)
public void setRChild(BinTreePosition c){
rChild = c;
}

// 返回当前节点后代元素的数目
public int getSize(){
return size;
}
// 在孩子发生变化后,更新当前节点及其祖先的规模
public void updateSize() {
//当前节点
size = 1;
if (hasLChild()){
// 左子树的规模
size += getLChild().getSize();
}
if (hasRChild()){
// 右子树的规模
size += getRChild().getSize();
}
if (hasParent()){
//递归更新各个真祖先的规模记录
getParent().updateSize();
}
}

// 返回当前节点的高度
public int getHeight(){
return height;
}
// 在孩子发生变化后,更新当前节点及其祖先的高度
public void updateHeight() {
// 先假设没有左、右孩子
height = 0;
if (hasLChild()){
// 左孩子的高度
height = Math.max(height, 1+getLChild().getHeight());
}
if (hasRChild()){
// 右孩子的高度
height = Math.max(height, 1+getRChild().getHeight());
}
if (hasParent()){
// 递归更新各个真祖先的高度记录
getParent().updateHeight();
}
}

// 返回当前节点的深度
public int getDepth(){
return depth;
}
// 在父亲发生变化后,更新当前节点及其后代的深度
public void updateDepth() {
// 当前节点
depth = hasParent() ? 1 + getParent().getDepth() : 0;
if (hasLChild()){
// 沿孩子引用逐层向下,
getLChild().updateDepth();
}
if (hasRChild()){
// 递归地更新所有后代的深度记录
getRChild().updateDepth();
}
}

// 按照中序遍历的次序,找到当前节点的直接前驱
public BinTreePosition getPrev(){
// 若左子树非空,则其中的最大者即为当前节点的直接前驱
if (hasLChild()){
return findMaxDescendant(getLChild());
}
// 至此,当前节点没有左孩子
if (isRChild()){
// 若当前节点是右孩子,则父亲即为其直接前驱
return getParent();
}
//至此,当前节点没有左孩子,而且是左孩子
BinTreePosition v = this;  //从当前节点出发
while (v.isLChild()){
// 沿左孩子链一直上升
v = v.getParent();
}
// 至此,v或者没有父亲,或者是父亲的右孩子
return v.getParent();
}

// 按照中序遍历的次序,找到当前节点的直接后继
public BinTreePosition getSucc() {
// 若右子树非空,则其中的最小者即为当前节点的直接后继
if (hasRChild()){
return findMinDescendant(getRChild());
}
// 至此,当前节点没有右孩子
if (isLChild()){
// 若当前节点是左孩子,则父亲即为其直接后继
return getParent();
}
// 至此,当前节点没有右孩子,而且是右孩子
// 从当前节点出发
BinTreePosition v = this;
while (v.isRChild()){
// 沿右孩子链一直上升
v = v.getParent();
}
// 至此,v或者没有父亲,或者是父亲的左孩子
return v.getParent();
}

// 断绝当前节点与其父亲的父子关系
// 返回当前节点
public BinTreePosition secede() {
// 如果有父节点
if (null != parent) {
// 当前节点为左孩子
if (isLChild()){
// 切断父亲指向当前节点的引用
parent.setLChild(null);
}else{
// 当前节点为右孩子,切断父节点指向当前节点的引用
parent.setRChild(null);
}
// 更新当前节点及其祖先的规模
parent.updateSize();
// 更新当前节点及其祖先的高度
parent.updateHeight();
// 切断当前节点指向原父亲的引用
parent = null;
// 更新节点及其后代节点的深度
updateDepth();
}
return this;
}

// 将节点c作为当前节点的左孩子
public BinTreePosition attachL(BinTreePosition c) {
// 如果有左孩子
if (hasLChild()){
// 摘除当前节点原先的左孩子
getLChild().secede();
}
if (null != c) {
// c脱离原父亲
c.secede();
// 确立新的父子关系
lChild = c;
c.setParent(this);
//更新当前节点及其祖先的规模
updateSize();
// 更新当前节点及其祖先的高度
updateHeight();
// 更新c及其后代节点的深度
c.updateDepth();
}
return this;
}

//将节点c作为当前节点的右孩子
public BinTreePosition attachR(BinTreePosition c) {
// 如果有右孩子
if (hasRChild()){
// 摘除当前节点原先的右孩子
getRChild().secede();
}
if (null != c) {
// c脱离原父亲
c.secede();
// 确立新的父子关系
rChild = c;
c.setParent(this);
// 更新当前节点及其祖先的规模
updateSize();
// 更新当前节点及其祖先的高度
updateHeight();
// 更新c及其后代节点的深度
c.updateDepth();
}
return this;
}

// 前序遍历
public MyIterator elementsPreorder() {
MyList list = new List_DLNode();
preorder(list, this);
// 返回这个列表的元素迭代器
return list.elements();
}

// 中序遍历
public MyIterator elementsInorder() {
MyList list = new List_DLNode();
inorder(list, this);
return list.elements();
}

// 后序遍历
public MyIterator elementsPostorder() {
MyList list = new List_DLNode();
postorder(list, this);
return list.elements();
}

// 层次遍历
public MyIterator elementsLevelorder() {
MyList list = new List_DLNode();
levelorder(list, this);
return list.elements();
}

/**************************** 辅助方法 ****************************/

// 在v的后代中,找出最小者
protected static BinTreePosition findMinDescendant(BinTreePosition v) {
if (null != v)
while (v.hasLChild()){
// 从v出发,沿左孩子链一直下降
v = v.getLChild();
}
// 至此,v或者为空,或者没有左孩子
return v;
}

// 在v的后代中,找出最大者
protected static BinTreePosition findMaxDescendant(BinTreePosition v) {
if (null != v)
while (v.hasRChild()){
// 从v出发,沿右孩子链一直下降
v = v.getRChild();
}
// 至此,v或者为空,或者没有右孩子
return v;
}

// 前序遍历以v为根节点的(子)树
protected static void preorder(MyList list, BinTreePosition v) {
// 递归基:空树
if (null == v)
return;
// 访问v
list.insertLast(v);
// 遍历左子树
preorder(list, v.getLChild());
// 遍历右子树
preorder(list, v.getRChild());
}

// 中序遍历以v为根节点的(子)树
protected static void inorder(MyList list, BinTreePosition v) {
// 递归基:空树
if (null == v) return;
// 遍历左子树
inorder(list, v.getLChild());
// 访问v
list.insertLast(v);
// 遍历右子树
inorder(list, v.getRChild());
}
// 后序遍历以v为根节的(子)树
protected static void postorder(MyList list, BinTreePosition v) {
// 递归基:空树
if (null == v) return;
// 遍历左子树
postorder(list, v.getLChild());
// 遍历右子树
postorder(list, v.getRChild());
// 访问v
list.insertLast(v);
}
//层次遍历以v为根节点的(子)树
protected static void levelorder(MyList list, BinTreePosition v) {
// 空队
Queue_List Q = new Queue_List();
// 根节点入队
Q.enqueue(v);
// Q不为空
while (!Q.isEmpty()) {
// 出队
BinTreePosition u = (BinTreePosition) Q.dequeue();
// 访问v
list.insertLast(u);
if (u.hasLChild()){
Q.enqueue(u.getLChild());
}
if (u.hasRChild()){
Q.enqueue(u.getRChild());
}
}
}
}


package codes04;
/*
* 基于单链表实现的队列
*/
public class Queue_List {
protected Node head;
protected Node tail;
protected int size;
public Queue_List(){
head = null;
tail = null;
size = 0;
}
public int getSize(){
return size;
}
public boolean isEmpty(){
return (0 == size) ? true : false;
}
// 入队
public void enqueue(Object obj){
Node node = new Node();
node.setElem(obj);
// 新节点作为尾节点插入
node.setNext(null);
if(0 == size){
// 若此前队列为空,直接插入
head = node;
}else{
// 将新节点接至队列末端
tail.setNext(node);
}
// 更新末节点引用
tail = node;
size++;
}
// 出队
public Object dequeue() throws ExceptionQueueEmpty{
if(0 == size){
throw new ExceptionQueueEmpty("意外:队列为空");
}
Object obj  = head.getElem();
head = head.getNext();
size--;
if(0 == size){
tail = null;
}
return obj;
}
// 取并不删除队首元素
public Object first() throws ExceptionQueueEmpty{
if(isEmpty()){
throw new ExceptionQueueEmpty("队列为空");
}
return head.getElem();
}
// 遍历
public void traversal(){
Node p = head;
while(p != null){
System.out.println(p.getElem() + " ");
p = p.getNext();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: