二叉树的三种遍历(一)--- 链式存储

如下有一颗树:

树的三种遍历结果分别为:

先序遍历:==》根、左、右

ABCDEFGH

中序遍历:==》左、根、右

CBEDFAGH

后序遍历:==》左、右、根

CEFDBHGA

将代码贴上来以便好查找^O^:

链式存储的二叉树长这样,如下:


二叉树的定义:

typedef char elemtype;
#define END '#'
typedef struct BtNode
{
	struct BtNode* leftchild;
	struct BtNode* rightchild;
	elemtype data;
}BtNode,*pBtNode;

创建一颗树:(利用先序的方法,将空结点用#表示)

BtNode* BuyNode()
{
	BtNode* bt=(pBtNode)malloc(sizeof(BtNode));
	if(bt==NULL)
		exit(1);

	return bt;
}

BtNode* Create()
{
	BtNode* bt=NULL;
	//bt=BuyNode();//ERROR
	elemtype elem;

	cin>>elem;

	if(elem!=END)
	{
		bt=BuyNode();//OK一定要放在使用之前

		bt->data=elem;
		bt->leftchild=Create();
		bt->rightchild=Create();
	}
	return bt;
}

三种遍历的递归写法:

void PreTraval(BtNode* ptr)//先序遍历
{
	if(ptr!=NULL)
	{
		cout<<ptr->data<<" ";//根结点
		PreTraval(ptr->leftchild);//左子树
		PreTraval(ptr->rightchild);//右子树
	}
	return ;
}

void OrderTraval(BtNode* ptr)//中序遍历
{
	if(ptr!=NULL)
	{
		OrderTraval(ptr->leftchild);//左子树
		cout<<ptr->data<<" ";根结点
		OrderTraval(ptr->rightchild);右子树
	}
	return ;
}

void PostTraval(BtNode* ptr)//后序遍历
{
	if(ptr!=NULL)
	{
		PostTraval(ptr->leftchild);//左子树
		PostTraval(ptr->rightchild);//右子树
		cout<<ptr->data<<" ";根结点
	}
	return ;
}

三种遍历的非递归写法:

void NicePreTraval(BtNode *ptr)//非递归的先序遍历
{
	//方法一:依旧是利用栈来实现,代码有点冗余
	//if(ptr==NULL)
	//	return ;

	//stack<pBtNode> st;
	//pBtNode pCur=ptr;
	//while(1)
	//{
	//	if(pCur==NULL && st.empty())
	//		break;
	//	else if(pCur!=NULL)
	//	{
	//		cout<<pCur->data<<" ";
	//		st.push(pCur);
	//		pCur=pCur->leftchild;
	//	}
	//	else if(pCur==NULL)
	//	{
	//		pCur=st.top();
	//		st.pop();
	//		pCur=pCur->rightchild;
	//	}
	//}

	//方法二:利用队列,先让右子树入队,再让左子树入队,完美!!!
	stack<BtNode*> st;
	if(ptr!=NULL)
		st.push(ptr);
	while(!st.empty())
	{
		ptr=st.top();st.pop();//一定要放在这,放在后面就会死循环,因为后边有其他元素入栈。
		cout<<ptr->data<<" ";
		
		if(ptr->rightchild!=NULL)
			st.push(ptr->rightchild);
		if(ptr->leftchild!=NULL)
			st.push(ptr->leftchild);
		
	}

}
void NiceOrderTraval(BtNode *ptr)//非递归的中序遍历
{
	//方法一:用死循环,代码看起来不是特别整洁
	//if(ptr==NULL)
	//	return ;

	//stack<pBtNode> st;
	//pBtNode pCur=ptr;
	//while(1)
	//{
	//	if(pCur==NULL && st.empty())
	//		break;
	//	else if(pCur!=NULL)
	//	{	
	//		st.push(pCur);
	//		pCur=pCur->leftchild;
	//	}
	//	else if(pCur==NULL)
	//	{
	//		pCur=st.top();
	//		cout<<pCur->data<<" ";
	//		st.pop();
	//		pCur=pCur->rightchild;
	//	}
	//}

	//方法二:两层while循环,代码比较整洁
	stack<BtNode*> st;
	while(ptr!=NULL || !st.empty())
	{
		while(ptr!=NULL)
		{
			st.push(ptr);
			ptr=ptr->leftchild;
		}
		ptr=st.top();
		cout<<ptr->data<<" ";
		st.pop();
		ptr=ptr->rightchild;
	}
	
}
void NicePostTraval(BtNode *ptr)//非递归的后序遍历
{
	//如果给树的节点上添加一个标志域,是不可行的,因为添加的标志位在一次访问之后全部都会被改变,在进行第二次访问时就无法达到预期的效果。
	//方法是在中序的非递归上进行改进,采用的是两个指针来进行标志
	stack<BtNode*> st;
	BtNode *tag=NULL;
	while(ptr!=NULL || !st.empty())
	{
		while(ptr!=NULL)
		{
			st.push(ptr);
			ptr=ptr->leftchild;
		}
		ptr=st.top();
		st.pop();
		if(ptr->rightchild==tag || ptr->rightchild==NULL)
		{
			cout<<ptr->data<<" ";
			tag=ptr;
			ptr=NULL;//必须得写!!!!!!否则ptr!=NULL,程序将一直无限死循环下去
		}
		else
		{
			st.push(ptr);
			ptr=ptr->rightchild;
		}
	}
}


END……

猜你喜欢

转载自blog.csdn.net/zhuoya_/article/details/80459751