把二元尋找樹轉變成排序的雙向鏈表
題目:
輸入一棵二元尋找樹,將該二元尋找樹轉換成一個排序的雙向鏈表。
要求不能建立任何新的結點,只調整指標的指向。
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();
}
}