把二元查找树转变成排序的双向链表

题目选自http://zhedahht.blog.163.com/(何海涛--程序员面试题精选100题)

把二元查找树转变成排序的双向链表_第1张图片

下面是按照书中分析的思路编写的code,或许看起来更简明

<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h> 

#define A 15

//二叉树前序遍历序列,-1表示空节点
int buffer[16]={10,6,4,-1,-1,8,-1,-1,14,12,-1,-1,16,-1,-1,-100};

//二叉树结构体
typedef struct binary_tree_node
{
	int data;
	struct binary_tree_node* ltree;
	struct binary_tree_node* rtree;
}Btnode;

//创建新节点
Btnode* create_node(void)
{
	Btnode* node;
	node=(Btnode*)malloc(sizeof(Btnode));
	return node;
}

//据前序序列创建二叉树
/*
	明确问题:

	(1)何时进行二叉树分支的切换

		①左分支遍历到叶子节点时

		②右分支有新的节点加入时

	(2)何时节点入栈

		新加入的非空节点

	(3)何时节点出栈

		某分支遍历到叶子节点时
*/
Btnode* create_tree(int* buf)
{
	Btnode* root;
	Btnode* pnode,*temp;
	Btnode* s[A];
	bool ltree=true;
	int index=0;
	int m=0;
	
	root=create_node();
	root->data=buf[index++];
	s[m++]=root;
	pnode=root;

	while(buf[index]!=-100)
	{
		if(ltree==true)
		{
			if(buf[index]==-1)
			{
				pnode->ltree=NULL;
				index++;
				ltree=false;
				pnode=s[--m];
			}
			else
			{
				temp=create_node();
				temp->data=buf[index++];
				pnode->ltree=temp;
				s[m++]=temp;
				pnode=temp;
			}
		}
		else
		{
			if(buf[index]==-1)
			{
				pnode->rtree=NULL;
				index++;
				pnode=s[--m];
			}
			else
			{
				temp=create_node();
				temp->data=buf[index++];
				pnode->rtree=temp;
				s[m++]=temp;
				pnode=temp;
				ltree=true;
			}
		}
	}

	return root;
}
/*
	基本思想:

	将左子树进行排序返回左子树的链尾,将右子树进行排序

	返回右子树的链首,将左子树链尾、根节点、右子树的链
	
	首进行连接

	明确问题:

	递归思想的实质也是栈操作,首先递归调用到一个不满足
	
	递归条件的状态,此时进行相应的操作并返回可能在回溯

	过程中用到的值,接下来进行回溯,回溯过程中进行相同
	
	的子任务处理。注:这里所说的相应操作是指->通过传入参
	
	数和返回值进行相应的操作。

	程序中parameter flag用于标记左子树还是右子树

*/
Btnode* tree2chain(Btnode* pnode,bool flag)
{
	Btnode* temp1,*temp2,*temp3;

	if(pnode->ltree==NULL && pnode->rtree==NULL)
	{
		return pnode;
	}

	if(pnode!=NULL)
	{
		temp1=tree2chain(pnode->ltree,true);
		temp2=pnode;
		temp3=tree2chain(pnode->rtree,false);
		temp1->ltree=temp2;
		temp2->ltree=temp3;
		temp3->rtree=temp2;
		temp2->rtree=temp1;
	}

	if(flag==true)
	{
		return temp3;
	}
	else
	{
		return temp1;
	}
}

int main(void)
{
	Btnode* root;
	Btnode* plist;

	root=create_tree(buffer);
	plist=root;
	while(plist->ltree!=NULL)		//记录链首
	{
		plist=plist->ltree;
	}
	tree2chain(root,true);	

	printf("正向遍历链表:\n");
	while(1)
	{
		printf("%d->",plist->data);
		if(plist->ltree!=NULL)
		{
			plist=plist->ltree;
		}
		else
		{
			break;
		}
	}
	printf("\n\n反向遍历链表:\n");
	while(1)
	{
		printf("%d<-",plist->data);
		if(plist->rtree!=NULL)
		{
			plist=plist->rtree;
		}
		else
		{
			break;
		}
	}
	printf("\n\n");

	system("pause");
	return 0;
}</span>
把二元查找树转变成排序的双向链表_第2张图片

至于非递归的方法可以按照中序遍历的方法将遍历各个节点的指针保存起来,最后再修改指针的指向


#include "stdafx.h"
#include <vector>
#include <iostream>
using namespace std;

#define A 16

//二叉树前序遍历序列
int buffer[16]={1,2,4,-1,-1,5,-1,-1,3,6,-1,-1,7,-1,-1,-100};

//二叉树结构体
typedef struct binary_tree_node
{
	int data;
	struct binary_tree_node* ltree;
	struct binary_tree_node* rtree;
}Btnode;

//创建新节点
Btnode* create_node(void)
{
	Btnode* node;
	node=(Btnode*)malloc(sizeof(Btnode));
	return node;
}

//据前序序列创建二叉树
/*
	明确问题:

	(1)何时进行二叉树分支的切换

		①左分支遍历到叶子节点时

		②右分支有新的节点加入时

	(2)何时节点入栈

		新加入的非空节点

	(3)何时节点出栈

		某分支遍历到叶子节点时
*/
Btnode* create_tree(int* buf)
{
	Btnode* root;
	Btnode* pnode,*temp;
	Btnode* s[A];
	bool ltree=true;
	int index=0;
	int m=0;
	
	root=create_node();
	root->data=buf[index++];
	s[m++]=root;
	pnode=root;

	while(buf[index]!=-100)
	{
		if(ltree==true)
		{
			if(buf[index]==-1)
			{
				pnode->ltree=NULL;
				index++;
				ltree=false;
				pnode=s[--m];
			}
			else
			{
				temp=create_node();
				temp->data=buf[index++];
				pnode->ltree=temp;
				s[m++]=temp;
				pnode=temp;
			}
		}
		else
		{
			if(buf[index]==-1)
			{
				pnode->rtree=NULL;
				index++;
				pnode=s[--m];
			}
			else
			{
				temp=create_node();
				temp->data=buf[index++];
				pnode->rtree=temp;
				s[m++]=temp;
				pnode=temp;
				ltree=true;
			}
		}
	}

	return root;
}

//递归方法前序遍历
void preorder_traversal(Btnode* pnode)
{
	if(pnode!=NULL)
	{
		printf("%d ",pnode->data);
	}
	else
	{
		return;
	}

	preorder_traversal(pnode->ltree);
	preorder_traversal(pnode->rtree);
	return;
}

vector<Btnode*> s;
Btnode* head;
void medDList(Btnode* node)
{
	if(node==NULL)
	{
		return;
	}
	else
	{
		medDList(node->ltree);
		if(s.empty())
		{
			s.push_back(node);
			head=node;
		}
		else
		{
			s.back()->rtree=node;
			node->ltree=s.back();
			s.push_back(node);
		}
		medDList(node->rtree);
	}
}

void showList()
{
	int len=s.size();
	Btnode* p=s.back();

	for(int i=0;i<len && p!=NULL;i++)
	{
		cout<<p->data<<"->";
		p=p->ltree;
	}
	printf("\b\b");
	cout<<"  ";
	cout<<endl;

	return;
}

int main(void)
{
	Btnode* root;
	root=create_tree(buffer);
	
	medDList(root);
	showList();
	
	system("pause");
	return 0;
}


你可能感兴趣的:(双向链表,查找树)