如何将二叉树转换为双向链表

参考: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;
			
	}
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值