第三次学习二叉树了,对层次遍历,非递归遍历有了进一步的认识.
解释:有n个结点的二叉树,除了根节点,其他每个结点都对应一条连线.所以由 n-1条线. 而度为2的对应两条连线,度为1的对应1条连线.所以 n-1 =n2*2+n1.
n个结点包括度分别为0,1,2的结点.所以n =n1+n2+n0 综合两个公式得出 n0 = n2+1
将代码分开来放了,方便和其他配合着用,开始用的自己写的栈,后来用STL的栈和队列了.
/*
bTree.h
*/
#include
#include
#include
#include
#include
using namespace std;
typedef char ElemType;
#define MAXSIZE 100
//定义二叉树结点
typedef struct BtNode {
ElemType data;
struct BtNode *lchild, *rchild;
}BtNode, *BTree;
//创建二叉树.使用#表示结点为空
void CreateBTree(BTree &BT);
//访问结点并输出
void visit(BTree bt);
//前序遍历
void PreNode(BTree bt);
//前序遍历(栈)
void PreOrder(BTree bt);
//度为2的结点数
int leaf_2(BTree bt);
//树的深度
int len_tree(BTree bt);
//二叉树的层次遍历
void LevelOrder(BTree bt);
//后续遍历(栈)
void LastOrder(BTree bt);
//二叉树 自下向上,自右向左
void BottomLevelOrder(BTree bt);
//非递归方式求树的深度
int BtDepth(BTree &bt);
//根据先序遍历和中序遍历求二叉树.
BTree PreInCreate(ElemType A[], ElemType B[],
int l1, int r1, int l2, int r2);
//判定二叉树是否是完全二叉树
//采用层次遍历,遇到空,看队列后面是否还有非空结点
bool isCompleteTree(BTree bt);
//将树中所有节点的左,右子树进行交换的函数
void SwapLeftRight(BTree bt);
//对于树中每个元素值为x的结点,删去以它为根的子树,并释放相应的空间.
void DelChildByX(BTree bt, ElemType x);
void FindXAncestor(BTree bt, ElemType x);
/*求非空二叉树b的宽度,
用层次遍历的方式,
*/
int MaxWidth(BTree bt);
/*
bTree.cpp
*/
#include "bTree.h"
//创建二叉树.使用#表示结点为空
void CreateBTree(BTree &BT)
{
ElemType data;
scanf_s("%c", &data);
if (data == '#') {
BT = NULL;
}
else
{
BT = (BTree)malloc(sizeof(BtNode));
BT->data = data;
CreateBTree(BT->lchild);
CreateBTree(BT->rchild);
}
}
//访问结点并输出
void visit(BTree bt)
{
if (bt->data != NULL){
printf("%2c", bt->data);
}
}
//前序遍历
void PreNode(BTree bt)
{
if (bt != NULL)
{
visit(bt);
PreNode(bt->lchild);
PreNode(bt->rchild);
}
}
//前序遍历(栈)非递归方式
void PreOrder(BTree bt)
{
stack S;
BtNode *p = bt;
while (p || !S.empty()){
if (p){
visit(p);
S.push(p);
p = p->lchild;
}
else
{
p = S.top();
S.pop();
p = p->rchild;
}
}
}
//后续遍历(栈)
void LastOrder(BTree bt)
{
stack S;
BtNode *p = bt, *r = NULL; //r指向最近访问过的结点
while (p || !S.empty())
{
if (p){ //走到最左边
S.push(p);
p = p->lchild;
}
else{
p=S.top();
if (p->rchild &&p->rchild != r){ //右子树不为空,且未被访问过
p = p->rchild;
S.push(p);
p = (*p).lchild;
}
else
{
visit(p);
r = p;
S.pop();
p = NULL;
}
}
}
}
//中序遍历
void InNode(BTree bt)
{
if (bt != NULL)
{
InNode(bt->lchild);
visit(bt);
InNode(bt->rchild);
}
}
//后序遍历
void LastNode(BTree bt)
{
if (bt != NULL)
{
LastNode(bt->lchild);
LastNode(bt->rchild);
visit(bt);
}
}
//二叉树的层次遍历,层次遍历使用队列.
void LevelOrder(BTree bt)
{
queue Q; //stl的队列
BtNode *p = bt;
Q.push(p); //根结点如队列
while (!Q.empty()){ //队列不为空
p = Q.front();
Q.pop();
visit(p);
if (p->lchild != NULL)
Q.push(p->lchild);
if (p->rchild != NULL)
Q.push(p->rchild);
}
}
//二叉树 自下向上,自右向左访问二叉树
void BottomLevelOrder(BTree bt)
{
queueQ;
stackS;
BtNode *p=bt;
Q.push(p);
while (!Q.empty()){
p = Q.front();
Q.pop();
S.push(p);
if (p->lchild != NULL)
Q.push(p->lchild);
if (p->rchild != NULL)
Q.push(p->rchild);
}
while (!S.empty()){
p=S.top();
S.pop();
visit(p);
}
}
/*非递归方式求二叉树的高度
用层次遍历来求.
*/
int BtDepth(BTree &bt)
{
if (!bt)
return 0;
BTree p;
int front = 0, rear = 0;
BtNode * Q[MAXSIZE]; //循环队列
Q[rear] = bt; //根节点入队
rear = (rear + 1) % MAXSIZE;
int last = 1, level = 0; //last指向下一层第一个结点的位置.
while (front != rear){
p = Q[front]; //出队列
front = (front + 1) % MAXSIZE;
if (p->lchild){ //左子树存在,左子树入队列
Q[rear] = p->lchild;
rear = (rear + 1) % MAXSIZE;
}
if (p->rchild){
Q[rear] = p->rchild;
rear = (rear + 1) % MAXSIZE;
}
if (front == last){
level++;
last = rear;
}
}
return level;
}
/*求非空二叉树b的宽度,
用层次遍历的方式,
*/
int MaxWidth(BTree bt)
{
if (!bt)
return 0;
BtNode * Q[MAXSIZE];
BTree p = NULL;
int front = 0, rear = 0;
int maxwidth = 0;
int num = 1;
Q[rear] = bt; //根节点入队列
rear =(rear + 1) % MAXSIZE; //指向队列下一个空位置.
int last = 1; //last指向下一层第一个结点.
while (front != rear){ //队列不为空
p = Q[front]; //出队列
front = (front + 1) % MAXSIZE;
if (p->lchild){ //左子树存在
Q[rear] = p->lchild;
rear = (rear + 1) % MAXSIZE;
}
if (p->rchild){
Q[rear] = p->rchild;
rear = (rear + 1) % MAXSIZE;
}
if (last != front){
num++;
}
else{ //last==front 说明一层扫描结束了
if (num > maxwidth)
maxwidth = num;
num = 1;
last = rear;
}
}
return maxwidth;
}
//树的深度
int len_tree(BTree bt)
{
int dl, dr, len;
if (bt == NULL){
return 0;
}
else
{
dl = len_tree(bt->lchild);
dr = len_tree(bt->rchild);
len = (dl >= dr) ? dl : dr;
return len + 1;
}
}
//度为2的结点数
int leaf_2(BTree bt)
{
if (bt == NULL) return 0;
if (bt->lchild != NULL && bt->rchild != NULL)
{
return 1 + leaf_2(bt->lchild)
+ leaf_2(bt->rchild);
}
return leaf_2(bt->lchild) + leaf_2(bt->rchild);
}
//度为0的结点数
int leaf_0(BTree bt)
{
if (bt == NULL) return 0;
if (bt->lchild == NULL && bt->rchild == NULL)
{
return 1;
}
return leaf_0(bt->lchild) + leaf_0(bt->rchild);
}
//根据先序遍历和中序遍历求二叉树.
BTree PreInCreate(ElemType A[], ElemType B[],
int l1, int r1, int l2, int r2)
{
int i;
BTree root = (BtNode *)malloc(sizeof(BtNode));
root->data = A[l1];
for (i = l2; B[i] != root->data; i++);
int llen = i - l2;
int rlen = r2 - i;
if (llen)
root->lchild = PreInCreate(A, B,
l1 + 1, l1 + llen, l2, l2 + llen - 1);
else
root->lchild = NULL;
if (rlen)
root->rchild = PreInCreate(A, B,
r1 - rlen + 1, r1, r2 - rlen + 1, r2);
else
root->rchild = NULL;
return root;
}
//判定二叉树是否是完全二叉树
//采用层次遍历,遇到空,看队列后面是否还有非空结点
bool isCompleteTree(BTree bt)
{
queue Q;
BtNode * p = bt;
Q.push(p);
while (!Q.empty()){
p = Q.front();
Q.pop();
if (p){
Q.push(p->lchild);
Q.push(p->rchild);
}
else{
while (!Q.empty()){
p = Q.front();
Q.pop();
if (p)
return 0;
}
}
}
return 1;
}
//将树中所有节点的左,右子树进行交换的函数
void SwapLeftRight(BTree bt)
{
if (bt ==NULL)
return;
BtNode *p = NULL;
p = bt->lchild;
bt->lchild = bt->rchild;
bt->rchild = p;
SwapLeftRight(bt->lchild);
SwapLeftRight(bt->rchild);
}
//------------------------------------
//对于树中每个元素值为x的结点,删去以它为根的子树,并释放相应的空间.
void Delchild(BTree bt)
{
if (bt){
Delchild(bt->lchild);
Delchild(bt->rchild);
free(bt);
}
}
void DelChildByX(BTree bt, ElemType x)
{
//用层次遍历的方法查找值为x的结点
queue Q;
BtNode *p=NULL;
int flag = 0;//保存是否找到x结点.
Q.push(bt);
while (!Q.empty()){
p = Q.front();
Q.pop();
if (p->data == x){
flag = 1;
break;
}
if (p->lchild !=NULL)
Q.push(p->lchild);
if (p->rchild !=NULL)
Q.push(p->rchild);
}
if (flag == 1){
Delchild(p->lchild); //删除该结点的左子树
p->lchild = NULL;
Delchild(p->rchild); //删除该结点的右子树
p->rchild = NULL;
}
else
return;
}
/*查找值为x的结点,打印值为x的结点的所有祖先.
用 非递归方式(栈) 后序遍历,栈中的所有节点就是x的祖先结点.
*/
void FindXAncestor(BTree bt, ElemType x)
{
stack S;
BtNode * p = bt, *r = NULL;
while (p || !S.empty()){
if(p){
if (p->data == x)
break;
S.push(p);
p = p->lchild;
}
else{
p = S.top();
if (p->data == x)
break;
if (p->rchild&& p->rchild != r){
p = p->rchild;
S.push(p);
p = p->lchild;
}
else{
S.pop();
r = p;
p = NULL;
}
}
}
if (p && p->data == x){
while (!S.empty()){
p = S.top();
visit(p);
S.pop();
}
}
}
/*main.cpp*/
#include
#include
#include
#include
#include "bTree.h"
using namespace std;
int main(){
BTree bt;
printf("先序建立一棵二叉树:\n");
CreateBTree(bt);
cout << endl;
printf("层次遍历:\n");
LevelOrder(bt);
cout << endl;
cout << MaxWidth(bt);
system("pause");
}