基础练习 应用堆栈进行树的遍历

创建二叉搜索树,通过堆栈实现前序遍历、中序遍历和后续遍历

1. 需要掌握的知识

二叉搜索树、树的遍历、堆栈

2. 代码框架(重点)

2.1 采用的数据结构

结构体数组

typedef int ElementType; //通过typedef增加灵活性,树节点的元素类型若改变,修改typedef语句即可
typedef struct BinarySearchTree *PtrBST;
struct BinarySearchTree
{
	ElementType data;
	PtrBST LeftTree;
	PtrBST RightTree;
};

2.2 各分支函数

  1. PreOrder()函数,通过堆栈实现树的前序遍历:根 左 右。
    核心思路
    (1)无论是树的哪种遍历,其访问顺序都是一样的:从根节点出发,按箭头指引方向访问各节点,每个节点均要访问三次。对于先序,对应第一次访问时就打印,对应结点入栈
    (2)通过堆栈模拟其访问顺序:先向左,边压栈边走,一直走到尽头,接下来,弹出栈顶元素并切换到其右子树,继续循环。这里比较抽象,建议多想一想
    在这里插入图片描述
void PreOrder_Stack(PtrBST Tree)
{
	stack<PtrBST> s; PtrBST T=Tree;
	
	while(T || !s.empty())
	{
		while(T) //向左子树走,一直走到尽头
		{
			s.push(T);
			cout<<T->data<<' ';
			T=T->LeftTree;
		}
		if(!s.empty()) //弹出栈顶元素,并切换到右子树
		{
			T=s.top();
			s.pop();
			T=T->RightTree;
		}	
	}
	return; 
}
  1. inOrder()函数,通过堆栈实现树的中序遍历:左 根 右
    核心思路:对于中序,第二次访问时打印,对应弹出栈顶元素的时候。因此代码可以继承先序遍历,调整打印位置即可
void InOrder_Stack(PtrBST Tree)
{
	stack<PtrBST> s; PtrBST T=Tree;
	
	while(T || !s.empty())
	{
		while(T)
		{
			s.push(T);
			T=T->LeftTree;
		}
		
		if(!s.empty())
		{
			T=s.top();
			s.pop();
			cout<<T->data<<' ';
			T=T->RightTree;
		}
	}
	return;
}
  1. PostOrder()函数,通过堆栈实现树的后序遍历:左 右 根
    核心思路
    (1)后序对应第三次访问时打印
    (2)后序遍历时,向左走到尽头,随后弹出栈顶元素,如果该节点没有右子树 或 右子树已访问,执行打印并将当前树赋值为空(避免再次切到右子树);否则,需要将该节点二次入栈并切换到其右子树,直到第二次弹出时再访问。代码有一定难度,需要结合实例仔细思考。
void PostOrder_Stack(PtrBST Tree)
{
	stack<PtrBST> s; PtrBST LastVisited;
	
	while(Tree || !s.empty())
	{
		while(Tree)
		{
			s.push(Tree);
			LastVisited=Tree;
			Tree=Tree->LeftTree;
		}
		
		Tree=s.top();
		s.pop();
		
		if(!Tree->RightTree || LastVisited==Tree->RightTree)
		{
			cout<<Tree->data<<' ';
			LastVisited=Tree; 
			Tree=NULL;
			
		}
		else
		{
			s.push(Tree);
			LastVisited=Tree;
			Tree=Tree->RightTree;
		}
	}
	return;
}
  1. 辅助函数 AddNode(),向树中添加结点
PtrBST AddNode(PtrBST Tree,ElementType value)
{
	if(!Tree)
	{
		Tree=(PtrBST)malloc(sizeof(struct BinarySearchTree));
		Tree->data=value; 
		Tree->LeftTree=NULL; 
		Tree->RightTree=NULL;
	}
	else
	{
		if(value < Tree->data) 
			Tree->LeftTree=AddNode(Tree->LeftTree,value); 	
		else
			Tree->RightTree=AddNode(Tree->RightTree,value);		
	}
	return Tree;
}
  1. 辅助函数 CreateBST(),调用AddNode()完成二叉搜索树的建立
PtrBST CreateBST(PtrBST Tree,int NodeNumber)
{
	ElementType value;
	for(int i=0;i<NodeNumber;i++)
	{
		cin>>value;
		Tree=AddNode(Tree,value);
	}
	return Tree;
}

3.完整编码

#include <stack>
#include <iostream>
#include <cstdlib>
using namespace std;
 

typedef int ElementType; //通过typedef增加灵活性,树节点的元素类型若改变,修改typedef语句即可
typedef struct BinarySearchTree *PtrBST;
struct BinarySearchTree
{
	ElementType data;
	PtrBST LeftTree;
	PtrBST RightTree;
};

PtrBST AddNode(PtrBST Tree,ElementType value);
PtrBST CreateBST(PtrBST Tree,int NodeNumber);

void PreOrder(PtrBST Tree);
void PreOrder_Stack(PtrBST Tree);

void InOrder(PtrBST Tree);
void InOrder_Stack(PtrBST Tree);

void PostOrder(PtrBST Tree);
void PostOrder_Stack(PtrBST Tree);
 
int main()
{
	int Nodes; 
	PtrBST BSTree=NULL;
	
	cin>>Nodes;
	BSTree=CreateBST(BSTree,Nodes);
	
	//PreOrder(BSTree); cout<<endl;
	//PreOrder_Stack(BSTree);
	
	//InOrder(BSTree); cout<<endl;
	//InOrder_Stack(BSTree);
	
	PostOrder(BSTree); cout<<endl;
	PostOrder_Stack(BSTree);
	
	return 0;
}

void PostOrder_Stack(PtrBST Tree)
{
	stack<PtrBST> s; PtrBST LastVisited;
	
	while(Tree || !s.empty())
	{
		while(Tree)
		{
			s.push(Tree);
			LastVisited=Tree;
			Tree=Tree->LeftTree;
		}
		
		Tree=s.top();
		s.pop();
		
		if(!Tree->RightTree || LastVisited==Tree->RightTree)
		{
			cout<<Tree->data<<' ';
			LastVisited=Tree; 
			Tree=NULL;
			
		}
		else
		{
			s.push(Tree);
			LastVisited=Tree;
			Tree=Tree->RightTree;
		}
		
	}
	return;
}

void PostOrder(PtrBST Tree)
{
	if(!Tree) return;
	PostOrder(Tree->LeftTree);
	PostOrder(Tree->RightTree);
	cout<<Tree->data<<' ';
}

void InOrder_Stack(PtrBST Tree)
{
	stack<PtrBST> s; 
	PtrBST T=Tree;
	
	while(T || !s.empty())
	{
		while(T)
		{
			s.push(T);
			T=T->LeftTree;
		}
		
		if(!s.empty())
		{
			T=s.top();
			s.pop();
			cout<<T->data<<' ';
			T=T->RightTree;
		}
	}
	return;
}

void InOrder(PtrBST Tree) //运用递归时一定要设定返回条件,否则会引起死循环 
{
	if(!Tree) return;
	InOrder(Tree->LeftTree);
	cout<<Tree->data<<' ';
	InOrder(Tree->RightTree); 
}

void PreOrder_Stack(PtrBST Tree)
{
	stack<PtrBST> s; PtrBST T=Tree;
	
	while(T || !s.empty())
	{
		while(T)
		{
			s.push(T);
			cout<<T->data<<' ';
			T=T->LeftTree;
		}
		if(!s.empty())
		{
			T=s.top();
			s.pop();
			T=T->RightTree;
		}	
	}
	return; 
}

void PreOrder(PtrBST Tree)
{
	if(!Tree) return;
	cout<<Tree->data<<" ";
	PreOrder(Tree->LeftTree);
	PreOrder(Tree->RightTree);
}

PtrBST AddNode(PtrBST Tree,ElementType value)
{
	if(!Tree)
	{
		//cout<<"Here is create the root!"<<endl;
		Tree=(PtrBST)malloc(sizeof(struct BinarySearchTree));
		Tree->data=value; 
		Tree->LeftTree=NULL; 
		Tree->RightTree=NULL;
	}
	else
	{
		//cout<<"Here is create the branch!"<<endl;
		if(value < Tree->data) 
			Tree->LeftTree=AddNode(Tree->LeftTree,value); 	
		else
			Tree->RightTree=AddNode(Tree->RightTree,value);		
	}
	return Tree;
}

PtrBST CreateBST(PtrBST Tree,int NodeNumber)
{
	ElementType value;
	for(int i=0;i<NodeNumber;i++)
	{
		cin>>value;
		//cout<<"input value: "<<value<<endl;
		Tree=AddNode(Tree,value);
	}
	return Tree;
}

参考信息

浙江大学 陈越、何钦铭老师主讲的数据结构

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值