题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。
比如将二元查找树
10
/ \
6 14
/ \ / \
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16。
分析:本题是微软的面试题。很多与树相关的题目都是用递归的思路来解决,本题也不例外。下面我们用两种不同的递归思路来分析。
思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。最近链接左子链表的最右结点(左子树的最大结点)、当前结点和右子链表的最左结点(右子树的最小结点)。从树的根结点开始递归调整所有结点。
思路二:我们可以中序遍历整棵树。按照这个方式遍历树,比较小的结点先访问。如果我们每访问一个结点,假设之前访问过的结点已经调整成一个排序双向链表,我们再把调整当前结点的指针将其链接到链表的末尾。当所有结点都访问过之后,整棵树也就转换成一个排序双向链表了。
参考网址:http://zhedahht.blog.163.com/blog/static/254111742007127104759245/
在此附上思路二的java实现:
//树节点类,包含节点的值,节点的左孩子、右孩子和父节点
public class TreeNode {
private int key;
private TreeNode leftchlid;
private TreeNode rightchild;
private TreeNode parent;
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public TreeNode getLeftchlid() {
return leftchlid;
}
public void setLeftchlid(TreeNode leftchlid) {
this.leftchlid = leftchlid;
}
public TreeNode getRightchild() {
return rightchild;
}
public void setRightchild(TreeNode rightchild) {
this.rightchild = rightchild;
}
public TreeNode getParent() {
return parent;
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
//构造函数
public TreeNode(int key,TreeNode leftchild,TreeNode rightchild,TreeNode parent){
this.key= key;
this.leftchlid= leftchild;
this.rightchild= rightchild;
this.parent= parent;
}
}
//二叉排序树类
public class BSTree {
private TreeNode root = null;
public TreeNode getRoot() {
return root;
}
public void setRoot(TreeNode root) {
this.root = root;
}
//将值key插入到二叉排序树中
public void insert(int key) {
TreeNode newnode = new TreeNode(key, null, null, null);
TreeNode parentnode = null;
TreeNode pnode = root;
if (root == null) {
root = newnode;
return;
}
while (pnode != null) {
parentnode = pnode;
if (key < pnode.getKey()) {
pnode = pnode.getLeftchlid();
} else if (key > pnode.getKey()) {
pnode = pnode.getRightchild();
} else {
// 树中已经有该值,直接返回
return;
}
}
if (key < parentnode.getKey()) {
parentnode.setLeftchlid(newnode);
newnode.setParent(parentnode);
} else {
parentnode.setRightchild(newnode);
newnode.setParent(parentnode);
}
}
/*搜索关键字为key的节点,如果该节点不再二叉树中,返回null,
*否则返回关键字为key的节点
*/
public TreeNode search(int key) {
TreeNode pnode = root;
while (pnode != null && pnode.getKey() != key) {
if (key < root.getKey()) {
pnode = pnode.getLeftchlid();
} else if (key > pnode.getKey()) {
pnode = pnode.getRightchild();
}
}
return pnode;
}
/*
* 返回以node节点为根节点的子树中key值最小的节点
*/
public TreeNode minElem(TreeNode node) {
if (root == null || node == null) {
return null;
}
while (node.getLeftchlid() != null) {
node = node.getLeftchlid();
}
return node;
}
/*
* 返回以node节点为根节点的子树中key值最大的节点
*/
public TreeNode maxElem(TreeNode node) {
if (root == null || node == null) {
return null;
}
while (node.getRightchild() != null) {
node = node.getRightchild();
}
return node;
}
/*
* 返回中序遍历中node节点的前驱节点
*/
public TreeNode precessor(TreeNode node) {
if (node == null || root == null) {
return null;
}
// 先判断该节点有没有左孩子,如果有做孩子,则返回maxElem(node.getleftchild()),如果
// 没有左孩子,再判断该节点是不是父节点的右孩子,如果是,则返回父节点,
// 如果不是,则找到该节点的某个祖先节点,该祖先节点是自己父节点的右孩子,返回该祖先节点的父节点
TreeNode parentnode = node.getParent();
if (node.getLeftchlid() != null) {
return maxElem(node.getLeftchlid());
}
if (parentnode.getRightchild() == node) {
return parentnode;
}
while (parentnode != null && parentnode.getLeftchlid() == node) {
node = parentnode;
parentnode = parentnode.getParent();
}
return parentnode;
}
/*
* 返回中序遍历中node节点的后继节点
*/
public TreeNode successor(TreeNode node) {
if (node == null || root == null) {
return null;
}
TreeNode parentnode = node.getParent();
// 如果节点有右孩子,则返回minElem(node.getrightchild()),如果
// 没有右孩子,再判断该节点是不是父节点的左孩子,如果是,则返回父节点
// 如果不是,则找到该节点的某个祖先节点,该祖先节点是自己父节点的左孩子
if (node.getRightchild() != null) {
return minElem(node.getRightchild());
}
if (node == parentnode.getLeftchlid()) {
return parentnode;
}
while (parentnode != null && node == parentnode.getRightchild()) {
node = parentnode;
parentnode = parentnode.getParent();
}
return parentnode;
}
//删除节点
public void delete(TreeNode node){
//判断要删除的节点或根节点是否为空
if(node == null){
//System.out.println("");
return;
}
TreeNode parentnode = node.getParent();
//该节点的左孩子和右孩子都为空
if(node.getLeftchlid() == null&&node.getRightchild() == null){
if(parentnode.getLeftchlid() == node)//该节点为父节点的左孩子
{
parentnode.setLeftchlid(null);
}
else
parentnode.setRightchild(null);
return;
}
//该节点的左孩子为空,右孩子不为空
if(node.getLeftchlid() == null&&node.getRightchild()!=null){
if(parentnode.getLeftchlid() == node)//该节点为父节点的左孩子
{
parentnode.setLeftchlid(node.getRightchild());
node.getRightchild().setParent(parentnode);
}
else //该节点为父节点的右孩子
{
parentnode.setRightchild(node.getRightchild());
node.getRightchild().setParent(parentnode);
}
return;
}
//该节点的右孩子为空,左孩子不为空
if(node.getLeftchlid()!=null&&node.getRightchild()==null){
if(parentnode.getLeftchlid()==node)//该节点为父节点的左孩子
{
parentnode.setLeftchlid(node.getLeftchlid());
node.getLeftchlid().setParent(parentnode);
}
else该节点为父节点的右孩子
{
parentnode.setRightchild(node.getLeftchlid());
node.getLeftchlid().setParent(parentnode);
}
return;
}
//该节点的左孩子和右孩子都不为空
TreeNode successornode = successor(node);
delete(successornode);
node.setKey(successornode.getKey());
}
public void delete(int key) {
TreeNode findnode = search(key);
if(findnode == null){
System.out.println("不存在该节点!");
return;
}
else
{
delete(findnode);
}
}
// 调整指针节点
public void convertToDoubleList(TreeNode currentnode){
TreeNode headnode = null;//指向循环列队头结点
TreeNode indexnode = null;//指向前一个节点
currentnode.setLeftchlid(indexnode);
if(indexnode == null){
headnode = currentnode;
}
else{
indexnode.setRightchild(currentnode);
}
indexnode = currentnode;
System.out.println(currentnode.getKey());
}
//中序遍历
public void inOrderBSTree(TreeNode root){
if(root == null){
return;
}
if(root.getLeftchlid()!=null){
inOrderBSTree(root.getLeftchlid());
}
convertToDoubleList(root);
if(root.getRightchild()!=null){
inOrderBSTree(root.getRightchild());
}
}
}
public class Test {
public static void main(String[] args) {
BSTree tree = new BSTree();
int[] array = {10,6,8,12,14,4,16};
for(int i =0;i<array.length;i++){
tree.insert(array[i]);
}
tree.inOrderBSTree(tree.getRoot());
//tree.delete(12);
//tree.inOrderBSTree(tree.getRoot());
}
}
测试结果:
4
6
8
10
12
14
16