剑指Offer——面试题27:二叉搜索树与双向链表

题目:输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,要求不能创建任何新的结点,只能调整树中结点指针的指向。

只能修改节点中的指针,那么简单一点的情形,应该就是将二叉树节点中的lchild指针当做转化后双向链表中的prev指针,rchild指针当做next指针。

思路类似于严蔚敏《数据结构》中的线索二叉树,但是略不同的地方是,对于一个有左子树的节点来说,他的左孩子指针要指向左子树中最大的节点,而不是原本的左孩子。举个典型的例子,根节点应当指向左子树的右孩子的右孩子的右孩子(只要存在右孩子,就一直继续下去)。同理,对于一个有右子树的节点来说,原本的右孩子指针应当指向右子树中最小的节点,而不是原本的右孩子。

通过GetLeftMax来得到左子树中的最大节点,通过GetRightMin来得到右子树中的最小节点,然后把这两个节点和根节点正确的连接即可。每次连接要操作4个指针,分别是把左侧最大的rchild指向根节点,根节点的lchild指向左侧最大,右侧最小的lchild指向根节点,根节点rchild指向右侧最小。当然这是在这个根节点的左右子树都存在的情况下的讨论。

我的代码用C/C++实现。

以下是数据结构定义的代码:

#include <iostream>
#include <stdlib.h>

using namespace std;

#define NULL 0

typedef struct TreeNode{
	int nValue;
	struct TreeNode* lchild;
	struct TreeNode* rchild;
}TreeNode;

  

以下是转换算法的代码:

TreeNode* GetLeftMax(TreeNode* const);
TreeNode* GetRightMin(TreeNode* const);

TreeNode* LinkNode(TreeNode* const pRoot){
	if (!pRoot) 
		return NULL;
	if (!pRoot->lchild && !pRoot->rchild)
		return pRoot;

	if (pRoot->lchild){
		TreeNode* pLeftMax = GetLeftMax(pRoot);
		pLeftMax->rchild = pRoot;
		pRoot->lchild = pLeftMax;
	}
	if (pRoot->rchild){
		TreeNode* pRightMin = GetRightMin(pRoot);
		pRightMin->lchild = pRoot;
		pRoot->rchild = pRightMin;
	}
	return pRoot;
}

TreeNode* GetLeftMax(TreeNode* const pRoot){
	TreeNode* LeftMax = LinkNode(pRoot->lchild);
	while (LeftMax->rchild)
		LeftMax = LeftMax->rchild;
	return LeftMax;
}

TreeNode* GetRightMin(TreeNode* const pRoot){
	TreeNode* RightMin = LinkNode(pRoot->rchild);
	while (RightMin->lchild)
		RightMin = RightMin->lchild;
	return RightMin;
}

TreeNode* GetHeadNodeOfDuLinkList(TreeNode* const pRoot){
	TreeNode* pHead = LinkNode(pRoot);
	if(pHead){
		while(pHead->lchild)
			pHead = pHead->lchild;
	}
	return pHead;
}

  

以下是测试用的代码,你也可以自己做一些改动:

static void BuildTree(TreeNode* &pRoot){
	pRoot = (TreeNode*)malloc(sizeof(TreeNode));
	pRoot->nValue = 4;
	pRoot->lchild = (TreeNode*)malloc(sizeof(TreeNode));
	pRoot->lchild->nValue = 2;
	pRoot->lchild->lchild = (TreeNode*)malloc(sizeof(TreeNode));
	pRoot->lchild->lchild->nValue = 1;
	pRoot->lchild->lchild->lchild = NULL;
	pRoot->lchild->lchild->rchild = NULL;
	pRoot->lchild->rchild = (TreeNode*)malloc(sizeof(TreeNode));
	pRoot->lchild->rchild->nValue = 3;
	pRoot->lchild->rchild->lchild = NULL;
	pRoot->lchild->rchild->rchild = NULL;
	pRoot->rchild = (TreeNode*)malloc(sizeof(TreeNode));
	pRoot->rchild->nValue = 6;
	pRoot->rchild->lchild = (TreeNode*)malloc(sizeof(TreeNode));
	pRoot->rchild->lchild->nValue = 5;
	pRoot->rchild->lchild->lchild = NULL;
	pRoot->rchild->lchild->rchild = NULL;
	pRoot->rchild->rchild = (TreeNode*)malloc(sizeof(TreeNode));
	pRoot->rchild->rchild->nValue = 7;
	pRoot->rchild->rchild->lchild = NULL;
	pRoot->rchild->rchild->rchild = NULL;
}

static void DeleteTree(TreeNode* pRoot){
	if(!pRoot)
		return;
	if(pRoot->lchild)
		DeleteTree(pRoot->lchild);
	if(pRoot->rchild)
		DeleteTree(pRoot->rchild);
	if(!pRoot->lchild && !pRoot->rchild)
		free(pRoot);
}

static void DeleteDuLinkList(TreeNode* pHead){
	if(!pHead)
		return;
	else{
		TreeNode* pNext = NULL;
		while(pHead->rchild){
			pNext = pHead->rchild;
			free(pHead);
			pHead = pNext;
		}
		free(pHead);
	}
}

static void PrintDuLinkList(TreeNode* const pHead){
	if(!pHead)
		return;
	else{
		TreeNode* pTemp = pHead;
		do{
			cout << pTemp->nValue <<endl;
			pTemp = pTemp->rchild;
		}while(pTemp);
	}
}

int main()
{
	TreeNode* pRoot = NULL;
	BuildTree(pRoot);
	TreeNode* pHead = GetHeadNodeOfDuLinkList(pRoot);
	PrintDuLinkList(pHead);
	DeleteDuLinkList(pHead);
	return 0;
}

  

只是跟书上给的不太一样。

posted @ 2014-09-18 22:32  Superpig0501  阅读(146)  评论(0编辑  收藏  举报