1、二叉树的非递归遍历
本题要求用非递归的方法实现对给定二叉树的 3 种遍历。
输入:输入二叉树结点构建二叉树
输出:输出 3 个函数分别按照访问顺序打印出结点的内容
include <stdio.h>
#include <stdlib.h>
typedef enum { false, true } bool;
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
int flag;
};
/*------堆栈的定义-------*/
typedef Position SElementType;
typedef struct SNode *PtrToSNode;
struct SNode {
SElementType Data;
PtrToSNode Next;
};
typedef PtrToSNode Stack;
/* 裁判实现,细节不表 */
Stack CreateStack();
bool IsEmpty( Stack S );
bool Push( Stack S, SElementType X );
SElementType Pop( Stack S ); /* 删除并仅返回S的栈顶元素 */
SElementType Peek( Stack S );/* 仅返回S的栈顶元素 */
/*----堆栈的定义结束-----*/
BinTree CreateBinTree(); /* 裁判实现,细节不表 */
void InorderTraversal( BinTree BT );
void PreorderTraversal( BinTree BT );
void PostorderTraversal( BinTree BT );
int main()
{
BinTree BT = CreateBinTree();
printf("Inorder:"); InorderTraversal(BT); printf("\n");
printf("Preorder:"); PreorderTraversal(BT); printf("\n");
printf("Postorder:"); PostorderTraversal(BT); printf("\n");
return 0;
}
void PreorderTraversal(BinTree BT) {//前序
Stack S=CreateStack();
while (BT||!IsEmpty(S)) {
while (BT) {
if (Push(S, BT)) {
printf(" %c", BT->Data);
BT=BT->Left;//一直向左走,直到没有左孩子
}
}
BT=Pop(S);//出栈
BT=BT->Right;//访问右子树
}
}
void InorderTraversal(BinTree BT) {//中序
Stack S=CreateStack();
while (BT||!IsEmpty(S)) {
while (BT){
if (Push(S, BT)) BT=BT->Left;
}
BT=Pop(S);
printf(" %c", BT->Data);
BT=BT->Right;
}
}
void PostorderTraversal(BinTree BT) {//后序
Stack S=CreateStack();
while (BT||!IsEmpty(S)) {
while (BT) {
if (Push(S, BT)) BT=BT->Left;
}
BT=Peek(S);
if (BT->flag!=1) {
BT->flag=1;
BT=BT->Right;
}
else {
BT=Pop(S);
printf(" %c",BT->Data);
BT=NULL;
}
}
}
ps:第一次遇到该结点就输出——前序遍历(入栈即访问);第二次遇到该结点就输出——中序遍历(出栈时访问);第三次遇到该结点就输出——后序遍历(左、右孩子已被访问时再出栈访问)。
前序和中序遍历的非递归实现都很简单,一直将左孩子入栈直到左孩子为空时再出栈,若出栈结点有右孩子则重复入栈操作,前序和中序遍历的区别只在于前序遍历是入栈时访问结点,中序遍历是出栈时访问结点。
后序遍历的非递归实现,通过结构体内的flag区分是第二次遇到该结点还是第三次遇到该结点。第一次遇到结点是压栈Push的时候,将flag设为0;第二次遇到结点Peek的时候,将flag设为1;第三次遇到该结点就是该输出的时候了,判断flag等于0还是1来确定该结点是否该输出。
2、是否二叉搜索树
本题要求实现函数,判断给定二叉树是否二叉搜索树。
输入:输入二叉树结点构建二叉树
输出:输出判断是否搜索二叉树
#include <stdio.h>
#include <stdlib.h>
typedef enum { false, true } bool;
typedef int ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
BinTree BuildTree(); /* 由裁判实现,细节不表 */
bool IsBST ( BinTree T );
int main()
{
BinTree T;
T = BuildTree();
if ( IsBST(T) ) printf("Yes\n");
else printf("No\n");
return 0;
}
bool IsBST ( BinTree T ){
if(!T) //如果树为空,则返回true,即为二叉搜索树
{
return true;
}
else if(!T->left&&!T->right){//只有一个根节点
return true;
}
else if(T->left&&!T->right){//存在左子树,不存在右子树
if(T->left->data<T->data)return IsBST(T->left);
else
return false;
}
else if(!T->left&&T->right){//存在右子树,不存在左子树
if(T->data<T->right)return IsBST(T->right);
else
return false;
}
else if(T->left&&T->right){//存在左、右子树
if(T->left->data<T->data &&T->right->data>T->data){
if(IsBST(T->left)&&IsBST(T->right))
return true;
else
return false;
}
else
return false;
}
}
ps:
验证二叉搜索树思路主要有两种:一种是递归,另一种是中序遍历。本题采用的是递归的方法,较为复杂。借鉴网上思想发现可以采用中序遍历,如果中序遍历出来的序列是递增的,即为二叉搜索树。
方法二(中序遍历):
int a[30],t=0; //数组a存储中序遍历序列
void inorderTraversal(BinTree BT) //递归中序遍历
{
if(BT)
{
inorderTraversal(BT->Left);
a[t]=BT->Data;
t++;
inorderTraversal(BT->Right);
}
}
bool IsBST ( BinTree T )
{
if(!T) //如果树为空,则返回true,即为二叉搜索树
{
return true;
}
inorderTraversal(T);
int last=a[0];
for(int i=1;i<t;i++) //判断中序遍历序列是否为递增
{
if(a[i]<=last)
{
return false;
}
last=a[i];
}
return true;
}
总结:今天复习了树的相关知识,学习了树的三种遍历方法的递归和非递归形式,明日计划复习图。