由于发现题集具有很好的借鉴效果,整个题目乃至答案如下:
http://blog.csdn.net/v_JULY_v/article/details/6057286
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
};
我个人的代码:
struct BSTreeNode
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};
BSTreeNode* bstree= new BSTreeNode;//Notice this; claim it obviously
void build_tree(BSTreeNode* bstree);//build a tree
void convert_tree2chain(BSTreeNode* bstree);
int _tmain(int argc, _TCHAR* argv[])
{
build_tree(bstree);
return 0;
}
void build_tree(BSTreeNode* bstree)
{
int tmp=0;
int count=0;
while(1)
{
cin>>tmp;
if(tmp==27)
{break;}
if(count==0)
{
bstree->m_nValue=tmp;
}
else if(bstree->m_nValue<tmp&&bstree->m_pLeft==NULL)
//本人程序与答案者的一大区别在于条件的判断上,NULL==bstree->m_nValue,能够防止产生相应的笔误赋值错误,还是这样防错性比较好
{//insert left leaf
BSTreeNode* bs_temp=new BSTreeNode;
bs_temp->m_nValue=tmp;
bstree->m_pLeft=bs_temp;
}else if(bstree->m_nValue>tmp&&bstree->m_pRight==NULL)
{//insert right leaf
BSTreeNode* bs_temp=new BSTreeNode;
bs_temp->m_nValue=tmp;
bstree->m_pRight=bs_temp;
}else if(bstree->m_nValue<tmp&&bstree->m_pLeft!=NULL)
{//if the node is null, then go to the next node
bstree=bstree->m_pLeft;
build_tree(bstree);//作递归调用
}
else if(bstree->m_nValue>tmp&&bstree->m_pRight!=NULL)
{
bstree=bstree->m_pRight;
build_tree(bstree);//作递归调用
}
}
}
void convert_tree2chain(BSTreeNode* bstree)
{
BSTreeNode* temp=new BSTreeNode;
temp->m_pLeft=bstree->m_pLeft;
temp->m_pRight=bstree->m_pRight;
//还是建立了一个中间节点,可以查找闲置的节点达到
while(bstree->m_pLeft!=NULL)
{//find the left leaf' right leaf 实际就是找节点的左边节点的最右与右边节点的最右
if(bstree->m_pLeft->m_pRight!=NULL)
bstree->m_pLeft=bstree->m_pLeft->m_pRight;
else
{
break;
}
}
while(bstree->m_pRight!=NULL)
{//find the right leaf' left leaf
if(bstree->m_pRight->m_pLeft!=NULL)
bstree->m_pRight=bstree->m_pRight->m_pLeft;
else
{
break;
}
}
convert_tree2chain(temp->m_pLeft);
convert_tree2chain(temp->m_pRight);
}
与其中答案的对比:
#include <stdio.h>
#include <iostream.h>
struct BSTreeNode
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};
typedef BSTreeNode DoubleList;
DoubleList * pHead;
DoubleList * pListIndex;
void convertToDoubleList(BSTreeNode * pCurrent);
// 创建二元查找树
void addBSTreeNode(BSTreeNode * & pCurrent, int value)
{
if (NULL == pCurrent)
{
BSTreeNode * pBSTree = new BSTreeNode();
pBSTree->m_pLeft = NULL;
pBSTree->m_pRight = NULL;//节点处赋值的应该将其置为空,防止出现空指针
pBSTree->m_nValue = value;
pCurrent = pBSTree;
}
else
{
if ((pCurrent->m_nValue) > value)
{
addBSTreeNode(pCurrent->m_pLeft, value);
}
else if ((pCurrent->m_nValue) < value)
{
addBSTreeNode(pCurrent->m_pRight, value);
}
else
{
//cout<<"重复加入节点"<<endl;
}
}
}
// 遍历二元查找树 中序
void ergodicBSTree(BSTreeNode * pCurrent)
{
if (NULL == pCurrent)
{
return;
}
if (NULL != pCurrent->m_pLeft)
{
ergodicBSTree(pCurrent->m_pLeft);
}
// 节点接到链表尾部
convertToDoubleList(pCurrent);
// 右子树为空
if (NULL != pCurrent->m_pRight)
{
ergodicBSTree(pCurrent->m_pRight);
}
}
// 二叉树转换成list
void convertToDoubleList(BSTreeNode * pCurrent)
{
pCurrent->m_pLeft = pListIndex;
if (NULL != pListIndex)
{
pListIndex->m_pRight = pCurrent;
}
else
{
pHead = pCurrent;
}
pListIndex = pCurrent;
cout<<pCurrent->m_nValue<<endl;
}
int main()
{
BSTreeNode * pRoot = NULL;
pListIndex = NULL;
pHead = NULL;
addBSTreeNode(pRoot, 10);
addBSTreeNode(pRoot, 4);
addBSTreeNode(pRoot, 6);
addBSTreeNode(pRoot, 8);
addBSTreeNode(pRoot, 12);
addBSTreeNode(pRoot, 14);
addBSTreeNode(pRoot, 15);
addBSTreeNode(pRoot, 16);
ergodicBSTree(pRoot);
return 0;
}