树——二叉树的遍历、代码实现以及线索二叉树

目录

 

遍历二叉树

定义

遍历方法

遍历算法描述

由二叉树得到遍历序列

先序遍历二叉树的操作

中序遍历二叉树的操作

后序遍历二叉树的操作

由遍历序列确定二叉树

已知先序序列和中序序列求二叉树

已知后序序列和中序序列求二叉树

遍历的算法实现(递归与非递归)

先序遍历算法(递归算法)

中序遍历算法(递归算法)

中序遍历算法(非递归算法)

后序遍历算法(递归算法)

遍历算法的分析

二叉树的层次遍历

算法思路(队列)

层次遍历算法实现

二叉树遍历算法的应用

应用1

应用2

线索二叉树

引入

定义

优化

线索二叉树的分类

进一步优化


遍历二叉树:

定义

遍历方法

重点研究前三种,因为前三种和后三种是对称的,所以只要会了前三种,后三种也就会了。

DLR——先(根)序遍历

LDR——中(根)序遍历

LRD——后(根)序遍历

遍历算法描述

由二叉树得到遍历序列

先序遍历二叉树的操作

中序遍历二叉树的操作

后序遍历二叉树的操作

例题

1.

2.用二叉树表示算术表达式:

由遍历序列确定二叉树

已知先序序列和中序序列求二叉树:

先序序列的第一个一定是根。

步骤:

已知后序序列和中序序列求二叉树:

后序序列的最后一个一定是根

遍历的算法实现(递归与非递归)

先序遍历算法(递归算法

中序遍历算法(递归算法

中序遍历算法(非递归算法

步骤

A、B先依次进栈

访问到 B 的左子树为空,则访问 B,B 出栈,B 的右子树也为空,则 D 进栈

访问 D 的左子树,为空,则访问 D ,D 出栈,访问D 的右子树,为空,返回到 A 

访问 A , A 出栈,接着C进栈

访问 C 的左子树,为空,C出栈,访问 C 的右子树为空,最后返回,此时栈为空

后序遍历算法(递归算法

遍历算法的分析

可以看到,如果去掉输出语句,从递归的角度看,三种算法是完全相同的,或者说这三种算法的访问路径是相同的,只是访问结点的时机不同。

如图所示:

时间复杂度都为O(n)。(都要沿着虚线走一遍,每个结点都访问并且只访问一次)

空间复杂度为O(n)。(最坏情况下,即单支情况下;栈占用的最大辅助空间)

二叉树的层次遍历:

如图:

算法思路(队列):

层次遍历算法实现

步骤

首先先让根结点a入队

将根结点a出队,同时让它的左右孩子b和f入队

将对头元素b出队,同时让它的左右孩子c和d入队

将对头元素f出队,同时让它的左孩子g入队(因其没有右孩子)

将对头元素c出队,因其没有左右孩子。所以不进行入队操作

将对头元素d出队,同时让它的左孩子e入队(因其没有右孩子)

将对头元素g出队,同时让它的右孩子h入队(因其没有左孩子)

将对头元素e出队,因其没有左右孩子。所以不进行入队操作

将对头元素h出队,因其没有左右孩子。所以不进行入队操作

此时队列为空,不能再进行出队操作,所以当前的层次遍历结束。

实现:

层次遍历也可以用来实现,但是比这个要麻烦。

二叉树遍历算法的应用:

应用1

.按先序遍历序列建立二叉树的二叉链表

我们可以看到如果我们直接输入ABCDEFG的话,它的树型结构是不唯一的。

解决方法:补充空结点

如:

代码实现:

#include<iostream>
#include<string>
using namespace std;
#define OK 1
#define OVERFLOW -2
#define MAXSIZE 100
typedef char Status;
//定义 
typedef struct BiNode
{
	char data;
	struct BiNode *lchild,*rchild;//左右孩子指针 
}BiNode,*BiTree;
Status Create(BiTree &T);//建立二叉树 
Status PreOrder(BiTree T);//按先序遍历输出 
Status InOrder(BiTree T);//按中序遍历输出 
Status PostOrder(BiTree T);//按后序遍历输出 
int main() 
{
	BiTree T;
    cout<<"二叉树创建成功"<<Create(T)<<endl;
    //函数调用 
    cout<<"按先序遍历输出:";
    PreOrder(T);
    cout<<endl; 
    cout<<"按中序遍历输出:";
    InOrder(T);
    cout<<endl; 
    cout<<"按后序遍历输出:";
    PostOrder(T);
    cout<<endl; 
	return 0;
} 
//建立二叉树 
Status Create(BiTree &T)
{
	char ch;
	cin>>ch;
	if(ch=='#') 
	T=NULL;
	else
	{
		if(!(T=new BiNode))
		exit(OVERFLOW);
		T->data=ch;
		Create(T->lchild);//递归构造左子树 
		Create(T->rchild);//递归构造右子树 
	}
	return OK;
}
//按先序遍历输出 
Status PreOrder(BiTree T)
{
	if(T==NULL) return OK;
	else
	{
		cout<<T->data;
		PreOrder(T->lchild);//递归遍历左子树 
		PreOrder(T->rchild);//递归遍历右子树
	}
}
//按中序遍历输出 
Status InOrder(BiTree T)
{
	if(T==NULL) return OK;
	else
	{
		InOrder(T->lchild);//递归遍历左子树 
		cout<<T->data;
		InOrder(T->rchild);//递归遍历右子树
	}
}
//按后序遍历输出 
Status PostOrder(BiTree T)
{
	if(T==NULL) return OK;
	else
	{
		PostOrder(T->lchild);//递归遍历左子树 
		PostOrder(T->rchild);//递归遍历右子树
		cout<<T->data;
	}
}

运行结果:

 

应用2

《1》复制二叉树

代码实现(以上图中的树为例):

#include<iostream>
#include<string>
using namespace std;
#define OK 1
#define OVERFLOW -2
#define MAXSIZE 100
typedef char Status;
//定义 
typedef struct BiNode
{
	char data;
	struct BiNode *lchild,*rchild;//左右孩子指针 
}BiNode,*BiTree;
Status Create(BiTree &T);//建立二叉树 
Status Copy(BiTree T,BiTree &NewT);//复制二叉树 
Status PreOrder(BiTree T);//按先序遍历输出 
int main() 
{
	BiTree T,NewT;
    cout<<"二叉树创建成功"<<Create(T)<<endl;
    //函数调用 
    Copy(T,NewT); 
    cout<<"按先序遍历输出新二叉树:";
    PreOrder(NewT);
    cout<<endl; 
	return 0;
} 
//建立二叉树 
Status Create(BiTree &T)
{
	char ch;
	cin>>ch;
	if(ch=='#') 
	T=NULL;
	else
	{
		if(!(T=new BiNode))
		exit(OVERFLOW);
		T->data=ch;
		Create(T->lchild);//递归构造左子树 
		Create(T->rchild);//递归构造右子树 
	}
	return OK;
}
//复制二叉树 
Status Copy(BiTree T,BiTree &NewT)
{
	if(T==NULL)
	{
		NewT=NULL;
		return 0;
	}
	else
	{
		NewT=new BiNode;
		NewT->data=T->data;
		Copy(T->lchild,NewT->lchild);//复制左子树 
		Copy(T->rchild,NewT->rchild);//复制右子树 
	} 
} 
//按先序遍历输出 
Status PreOrder(BiTree NewT)
{
	if(NewT==NULL) return OK;
	else
	{
		cout<<NewT->data;
		PreOrder(NewT->lchild);//递归遍历左子树 
		PreOrder(NewT->rchild);//递归遍历右子树
	}
}

运行结果:

 

《2》计算二叉树深度

代码实现(以《1》中的树为例):

#include<iostream>
#include<string>
using namespace std;
#define OK 1
#define OVERFLOW -2
#define MAXSIZE 100
typedef char Status;
//定义 
typedef struct BiNode
{
	char data;
	struct BiNode *lchild,*rchild;//左右孩子指针 
}BiNode,*BiTree;
Status Create(BiTree &T);//建立二叉树 
int Depth(BiTree T);//计算树的深度 
int main() 
{
	BiTree T,NewT;
    cout<<"二叉树创建成功"<<Create(T)<<endl;
    //函数调用 
    cout<<"树的深度:"<<Depth(T);
	return 0;
} 
//建立二叉树 
Status Create(BiTree &T)
{
	char ch;
	cin>>ch;
	if(ch=='#') 
	T=NULL;
	else
	{
		if(!(T=new BiNode))
		exit(OVERFLOW);
		T->data=ch;
		Create(T->lchild);//递归构造左子树 
		Create(T->rchild);//递归构造右子树 
	}
	return OK;
}
//计算树的深度
int Depth(BiTree T)
{
	int m,n;
	if(T==NULL)//如果为空树返回0 
	return 0;
	else
	{
		m=Depth(T->lchild);
		n=Depth(T->rchild);
		if(m>n)
		return (m+1);
		else
		return (n+1);
	}
}

运行结果:

 

《3》计算二叉树的结点总数

代码实现(以上图中的树为例):

#include<iostream>
#include<string>
using namespace std;
#define OK 1
#define OVERFLOW -2
#define MAXSIZE 100
typedef char Status;
//定义 
typedef struct BiNode
{
	char data;
	struct BiNode *lchild,*rchild;//左右孩子指针 
}BiNode,*BiTree;
Status Create(BiTree &T);//建立二叉树 
int NodeCount(BiTree T);//计算二叉树的结点总数  
int main() 
{
	BiTree T,NewT;
    cout<<"二叉树创建成功"<<Create(T)<<endl;
    //函数调用 
    cout<<"该树的结点总数为:"<<NodeCount(T)<<endl;
	return 0;
} 
//建立二叉树 
Status Create(BiTree &T)
{
	char ch;
	cin>>ch;
	if(ch=='#') 
	T=NULL;
	else
	{
		if(!(T=new BiNode))
		exit(OVERFLOW);
		T->data=ch;
		Create(T->lchild);//递归构造左子树 
		Create(T->rchild);//递归构造右子树 
	}
	return OK;
}
//计算二叉树的结点总数
int NodeCount(BiTree T)
{
	if(T==NULL)
	return 0;
	else
	{
		return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
	}
}

运行结果:

 

《4》计算二叉树叶子结点数

代码实现(以《3》中的树为例):

#include<iostream>
#include<string>
using namespace std;
#define OK 1
#define OVERFLOW -2
#define MAXSIZE 100
typedef char Status;
//定义 
typedef struct BiNode
{
	char data;
	struct BiNode *lchild,*rchild;//左右孩子指针 
}BiNode,*BiTree;
Status Create(BiTree &T);//建立二叉树 
int LeadCount(BiTree T);//计算二叉树的叶子结点数  
int main() 
{
	BiTree T,NewT;
    cout<<"二叉树创建成功"<<Create(T)<<endl;
    //函数调用 
    cout<<"该树的叶子结点数为:"<<LeadCount(T)<<endl;
	return 0;
} 
//建立二叉树 
Status Create(BiTree &T)
{
	char ch;
	cin>>ch;
	if(ch=='#') 
	T=NULL;
	else
	{
		if(!(T=new BiNode))
		exit(OVERFLOW);
		T->data=ch;
		Create(T->lchild);//递归构造左子树 
		Create(T->rchild);//递归构造右子树 
	}
	return OK;
}
//计算二叉树的叶子结点数
int LeadCount(BiTree T)
{
	if(T==NULL)//如果是空树返回0 
	return 0;
	else if(T->lchild==NULL&&T->rchild==NULL)
	return 1;//如果是叶子结点返回1 
	else
	{
		return LeadCount(T->lchild)+LeadCount(T->rchild);
	}
}

 运行结果:

线索二叉树

引入

定义:

利用二叉链表中的空指针域:

举例:

优化:

线索二叉树的分类

进一步优化:

发布了23 篇原创文章 · 获赞 30 · 访问量 8673

猜你喜欢

转载自blog.csdn.net/l218623/article/details/104279449
今日推荐