package cn.com.amazon.basic.one; 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 }; 思路汇总: (1)每访问到一个parent,递归左子树,递归右子树,连接左子树的最左边,右子树的最右边与根节点的结合处。故递归函数必须标明当前子树左右情况。 (2)中序遍历树,记录一个pre,然后每访问到一个节点,就将其加入双向链表中,具体即为与pre的操作。 */ public 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()); } } }
BSTree.java
猜你喜欢
转载自596392912.iteye.com/blog/2305073
今日推荐
周排行