把二元查找树转变成排序的双向链表 java版本

把二元查找树转变成排序的双向链表
 题目:
 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
 要求不能创建任何新的结点,只调整指针的指向。
   10
  / \
  6  14
 / \ / \
 4  8 12 16
 转换成双向链表
 4=6=8=10=12=14=16。
 
 首先我们定义的二元查找树 节点的数据结构如下:
 struct BSTreeNode
 {
  int m_nValue; // value of node
  BSTreeNode *m_pLeft; // left child of node
  BSTreeNode *m_pRight; // right child of node
 };

 


/**
 *
 */
package com.lhp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 1.把二元查找树转变成排序的双向链表
 题目:
 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
 要求不能创建任何新的结点,只调整指针的指向。
   10
  / \
  6  14
 / \ / \
 4  8 12 16
 转换成双向链表
 4=6=8=10=12=14=16。
 
 首先我们定义的二元查找树 节点的数据结构如下:
 struct BSTreeNode
 {
  int m_nValue; // value of node
  BSTreeNode *m_pLeft; // left child of node
  BSTreeNode *m_pRight; // right child of node
 };
 */


/**
 * 二元查找树
 */
class BSTree implements Cloneable,Serializable {
 /**
  * v0.8
  */
 private static final long serialVersionUID = -7240326774488306261L;

 private BSNode m_root; // 根节点
 
 private BSNode tempListNode; // 创建doubleList的时候使用的临时变量
 private BSNode tempListHead; // 创建doubleList的时候使用的临时变量
 
 public void setM_root(BSNode mRoot) {
  m_root = mRoot;
 }

 public BSNode getM_root() {
  return m_root;
 }
 
 /**
  * 深拷贝
  */
 public Object clone() {
  try {
   // 没有去想树的节点拷贝算法,先用这种简便方法,再复杂的类型拷贝也不怕,不过所有相关类都必须是Serializable
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   ObjectOutputStream oos = new ObjectOutputStream(baos);
   oos.writeObject(this);
   oos.close();
   ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
   ObjectInputStream ois = new ObjectInputStream(bais);
   Object ob = ois.readObject();
   ois.close();
   return (BSTree) ob;
  } catch (Exception e) {
   System.out.println("CloneNotSupportedException: " + e);
   e.printStackTrace();
  }
  return null;
 }
 
 /**
  * 增加子节点
  * @param 二元查找树节点
  */
 public synchronized void addNode(BSNode node) {
  if (null == this.m_root) {
   this.m_root = node;
   return;
  }
  
  BSNode tempNode = this.m_root;
  
  while (true) {
   if (node.getM_nValue() > tempNode.getM_nValue()) { // 大于父节点
    if (null == tempNode.getM_pRight()) {
     tempNode.setM_pRight(node);
     return;
    } else {
     tempNode = tempNode.getM_pRight();
     continue;
    }
   } else if (node.getM_nValue() < tempNode.getM_nValue()) { // 小于父节点
    if (null == tempNode.getM_pLeft()) {
     tempNode.setM_pLeft(node);
     return;
    } else {
     tempNode = tempNode.getM_pLeft();
     continue;
    }
   } else { // 等于父节点
    return;
   }
  }
 }
 
 /**
  * 生成双向链表
  * @return 双向链表
  * @throws CloneNotSupportedException
  */
 public synchronized BSDoubleList changeToDoubleList() {
  BSTree tempTree = (BSTree) this.clone(); // 临时树,替死鬼,被转换得面目全非,垃圾回收了吧...
  // 其实改为changeTreeToDoubleList(this.getM_root());才符合题意,不过个人喜欢使用深拷贝,不破坏原来的树
  if (null != tempTree) {
   changeTreeToDoubleList(tempTree.getM_root());
  }
  BSDoubleList dlist = new BSDoubleList();
  dlist.setHead(tempListHead);
  return dlist;
 }
 
 private void changeTreeToDoubleList(BSNode node) {
  if (null == node) {
   return;
  }
  if (null != node.getM_pLeft()) {
   changeTreeToDoubleList(node.getM_pLeft());
  }
  // -------------转换---------------
  node.setM_pLeft(tempListNode);
  if (null == tempListNode){
   tempListHead = node;
  } else {
   tempListNode.setM_pRight(node);
  }
  //---------------------------------
  tempListNode = node;
  if (null != node.getM_pRight()) {
   changeTreeToDoubleList(node.getM_pRight());
  }
 }
 
 
 /**
  * 打印中序遍历
  */
 public synchronized void print() {
  if (null == this.m_root) {
   System.out.print("HashCode: " + this.hashCode() +  "; 空树;");
   return;
  }
  System.out.print("HashCode: " + this.hashCode() +  "; 树: ");
  print(this.m_root);
  System.out.println();
 }
 
 private void print(BSNode node) {
  if (null != node) {
   print(node.getM_pLeft());
   System.out.print(node.getM_nValue() + " ");
   print(node.getM_pRight());
  }
 }
}

/**
 * 二元查找树(双向链表)节点
 */
class BSNode implements Serializable {
 /**
  * v1.0
  */
 private static final long serialVersionUID = 6136767364555910395L;
 
 private int m_nValue; // 值
 private BSNode m_pLeft; // 左(前驱)节点
 private BSNode m_pRight; // 右(后继)节点
 
 public BSNode(int value) {
  this.m_nValue = value;
 }
 
 public int getM_nValue() {
  return m_nValue;
 }
 public void setM_nValue(int mNValue) {
  m_nValue = mNValue;
 }
 public BSNode getM_pLeft() {
  return m_pLeft;
 }
 public void setM_pLeft(BSNode mPLeft) {
  m_pLeft = mPLeft;
 }
 public BSNode getM_pRight() {
  return m_pRight;
 }
 public void setM_pRight(BSNode mPRight) {
  m_pRight = mPRight;
 }
}

/**
 * 双向链表
 */
class BSDoubleList {
 private BSNode head; // 最左边的头结点

 public BSNode getHead() {
  return head;
 }

 public void setHead(BSNode head) {
  this.head = head;
 }
 
 public synchronized void print() {
  if (null != this.head) {
   System.out.print("HashCode: " + this.hashCode() +  "; 双向链表(正向): ");
   while (true) {
    if (null != this.head.getM_pRight()) {
     System.out.print(this.head.getM_pRight().getM_nValue() + " ");
     this.head = this.head.getM_pRight(); 
    } else {
     break;
    }
   }
   System.out.println();
   System.out.print("HashCode: " + this.hashCode() +  "; 双向链表(逆向): ");
   while (true) {
    if (null != this.head) {
     System.out.print(this.head.getM_nValue() + " ");
     this.head = this.head.getM_pLeft(); 
    } else {
     break;
    }
   }
  } else {
   System.out.println("HashCode: " + this.hashCode() + "; 空链表;");
  }
  System.out.println();
 }
 
}

public class One {
 public static void main(String[] args) {
  BSTree tree = new BSTree();
  tree.addNode(new BSNode(10));
  tree.addNode(new BSNode(6));
  tree.addNode(new BSNode(14));
  tree.addNode(new BSNode(4));
  tree.addNode(new BSNode(8));
  tree.addNode(new BSNode(12));
  tree.addNode(new BSNode(16));
  tree.print();
  BSDoubleList dlist = tree.changeToDoubleList();
  dlist.print();
  System.out.println("原来的树:");
  tree.print();
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值