参考:1,http://blog.csdn.net/anialy/article/details/7645535
2《剑指offer》
最近在研究算法相关的内容,看到关于题目所描述的问题感觉挺有意思,于是查找相关资料。其中参考资料1中的那篇博客所提供的思想最为简单也最容易理解,可惜是用C++实现,对于对C++不太熟悉的人可能理解比较有压力,于是我将其翻译为大家所熟悉的C语言进行实现。参考资料2中所提供的思想也比较简单,可惜实现起来细节很难把握(看了思想后,我就花费了好久并且参考答案最后才完整跑通),但是其代码特别少,也特别简练。
下面我介绍一下参考1的思想
每次递归我没都会选取左子树的最大节点,和右子树的最小节点(关于怎么选可以参考二叉搜索树相关内容)然后我们将当前节点的左指针指向左子树的最大值,将左子树的最大节点的右指针指向当前节点,将当前节点的右指针指向右子树的最小值节点,将右子树的左指针指向当前节点(总之就是左指针永远指向两个节点的最小值节点,右指针指向最大值节点)这样递归就可以解决这个问题。代码如下(很容易编写)
struct node
{
int data;
struct node *left;
struct node *right;
};
struct node *Head;
struct node *GetleftMax(struct node *ptr)
struct node *temp = ptr;
/*
if(ptr != NULL)
return
*/
if(temp == NULL)
return ptr;
while(temp->right != NULL)
{
temp = temp->right;
}
return temp;
}
struct node *GetrightMin(struct node *ptr) {
struct node *temp = ptr;
/*
if(ptr != NULL)
return
*/
if(temp == NULL)
return ptr;
while(temp->left != NULL)
{
temp = temp->left;
}
return temp;
}
void convert(struct node *head)
{
struct node *leftmax;
struct node *rightmin;
if(head != NULL)
if(head->left != NULL)
{
leftmax = GetleftMax(head->left);
convert(head->left);
leftmax->right = head;
head->left = leftmax;
}
if(head->right != NULL)
{
rightmin = GetrightMin(head->right);
convert(head->right);
rightmin->left = head;
head->right = rightmin;
}
}
上述GetleftMax即为获得左子树最大值节点的代码,GetrightMin即为获得有子树的最大值代码,Convert即为转换递归代码。比较简单就不做解释了。
参考二的思想也很简单,我们用一个plastnode指向最近一个已经转换好的节点,连续递归。
void convert2(struct node *head, struct node **plastnode)
{
if(head == NULL)
return;
struct node *current;
current = head;
if(current->left != NULL)
convert2(current->left, plastnode);
current->left = *plastnode;
if(*plastnode != NULL)
(*plastnode)->right = current;
*plastnode = current;
if(current->right != NULL)
convert2(current->right, plastnode);
}
如果指向指针的指针大家不太理解可以将其定义为全局变量。下面给一段参考1中所给的测试用例(很那啥。。。)。
int main()
{
struct node *p7 =(struct node *) malloc(sizeof(struct node));
p7->data = 7;
p7->left = NULL;
p7->right = NULL;
struct node *p4 =(struct node *) malloc(sizeof(struct node));
p4->data = 4;
p4->left = NULL;
p4->right = NULL;
struct node *p10 =(struct node *) malloc(sizeof(struct node));
p10->data = 10;
p10->left = NULL;
p10->right = NULL;
struct node *p1 =(struct node *) malloc(sizeof(struct node));
p1->data = 1;
p1->left = NULL;
p1->right = NULL;
struct node *p5 =(struct node *) malloc(sizeof(struct node));
p5->data = 5;
p5->left = NULL;
p5->right = NULL;
struct node *p9 =(struct node *) malloc(sizeof(struct node));
p9->data = 9;
p9->left = NULL;
p9->right = NULL;
struct node *p13 =(struct node *) malloc(sizeof(struct node));
p13->data = 13;
p13->left = NULL;
p13->right = NULL;
struct node *p0 =(struct node *) malloc(sizeof(struct node));
p0->data = 0;
p0->left = NULL;
p0->right = NULL;
struct node *p2 =(struct node *) malloc(sizeof(struct node));
p2->data = 2;
p2->left = NULL;
p2->right = NULL;
struct node *p12 =(struct node *) malloc(sizeof(struct node));
p12->data = 12;
p12->left = NULL;
p12->right = NULL;
struct node *p14 =(struct node *) malloc(sizeof(struct node));
p14->data = 14;
p14->left = NULL;
p14->right = NULL;
struct node *p11 =(struct node *) malloc(sizeof(struct node));
p11->data = 11;
p11->left = NULL;
p11->right = NULL;
p7->left = p4; p7->right = p10; p4->left = p1; p4->right = p5;
p10->left = p9; p10->right = p13; p1->left = p0; p1->right = p2;
p13->left = p12;p13->right = p14 ; p12->left = p11;
struct node *plastnode = NULL ;
convert2(p7,&plastnode);
while(p0 != NULL)
{
printf("%d ", p0->data);
p0 = p0->right;
}
//Inorder(p7);
}
手动建立二叉树 。
下面我给一段,自动建立二叉树的代码(不太规范但是,建立二叉树没有任何问题。)
struct node
{
int data;
struct node *lchild;
struct node *rchild;
};
/*
struct node* SearchBst(struct node *&head, int key)
{
if(head==NULL)
return head;
if(head->data == key)
return;
}
*/
//find the insert position
struct node* SearchPosi(struct node *&head, int key)
{
if(head == NULL)
return head;
struct node *PrePos;
struct node *Pos;
PrePos = Pos = head;
while(Pos != NULL)
{
PrePos = Pos;
if(Pos->data == key)
{
#ifdef Debug
printf("data exit\n");
#endif
return NULL;
}
else if(Pos->data < key)
Pos = Pos->rchild;
else
Pos = Pos->lchild;
}
return PrePos;
}
//@@@@insert data, if there is the same figure we ignore it
void Insert(struct node *&head, int key)
{
struct node *Node = NULL;
struct node *Pos = NULL;
if(head==NULL)
{
head = (struct node *)malloc(sizeof(struct node));
head->data = key;
head->lchild = NULL;
head->rchild = NULL;
}
else
{
Pos = SearchPosi(head, key);
if(Pos == NULL) // xiang tong shi hui fan hui NULL
return;
Node = (struct node *)malloc(sizeof(struct node));
Node->data = key;
Node->lchild = NULL;
Node->rchild = NULL;
if(Pos->data < key)
Pos->rchild = Node;
else
Pos->lchild = Node;
}
}