链式二叉树的各种方式遍历,递归,非递归,层序的队列和数组实现

head.h

#ifndef HEAD_H_INCLUDED
#define HEAD_H_INCLUDED

#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<malloc.h>

using namespace std;//标准程序库的所有标识符都被定义在这个名为std的命名空间

typedef int TElemType;
typedef struct BinaryTree
{
    TElemType data;
    struct BinaryTree *Left;
    struct BinaryTree *Right;
}BTree;

BTree* CreateBinaryTree();//创建二叉树
void PreOderTraverse1(BTree*T);//前序遍历
void InOderTravers1(BTree*T);//中序遍历
void PostOderTravers1(BTree*T);//后序遍历
void PreOderTraverse2(BTree*T);//非递归前序遍历
void InOderTravers2(BTree*T);//非递归中序遍历
void PostOderTravers2(BTree*T);//非递归后序遍历
void LeavelOrderTravers1(BTree*T);//用队列实现的层序遍历
void LeavelOrderTravers2(BTree*T);//用数组实现的层序遍历
void Copy(BTree*T,BTree*NT);//复制树
void DestoryTree(BTree*T);//销毁树
int Depth(BTree*T);//计算二叉树深度
int NodeCount(BTree*T);//计算节点个数

#endif // HEAD_H_INCLUDED

main.cpp

#include"head.h"

int main()
{

    printf("************************************\n");
    printf("请输入数字选择要执行的操作\n");
    puts("1. 构造二叉树");
	puts("2. 前序遍历二叉树");
	puts("3. 中序遍历二叉树");
	puts("4. 后续遍历二叉树");
	puts("5. 非递归前序遍历二叉树");
	puts("6. 非递归中序遍历二叉树");
	puts("7. 非递归后序遍历二叉树");
	puts("8. 队列实现的层序遍历二叉树");
	puts("9. 数组实现的层序遍历二叉树");
	puts("10. 复制二叉树");
	puts("11. 计算二叉树深度");
	puts("12. 计算二叉树结点个数");
	puts("13. 销毁二叉树");
	printf("\n********************************\n\n");
	int a;
	while(1)
    {
        puts("请选择要执行的操作\n");
        scanf("%d",&a);
        if(a==0) break;
        switch(a)
        {
        case 1 :
            BTree*T;
            T=CreateBinaryTree();
            break;
        case 2 :
            puts("前序遍历如下:");
            PreOderTraverse1(T);
            break;
        case 3 :
            puts("中序遍历如下:");
            InOderTravers1(T);
            break;
        case 4 :
            puts("后序遍历如下:");
            PostOderTravers1(T);
            break;
        case 5 :
            puts("前序非递归遍历如下:");
            PreOderTraverse2(T);
            break;
        case 6 :
            puts("中序非递归遍历如下:");
            InOderTravers2(T);
            break;
        case 7 :
            puts("后序非递归遍历如下:");
            PostOderTravers2(T);
            break;
        case 8 :
            puts("队列层序递归如下:");
            LeavelOrderTravers1(T);
            break;
        case 9 :
            puts("数组层序递归如下:");
            LeavelOrderTravers2(T);
            break;
        case 10 :
            BTree*NT;
            Copy(T,NT);
            break;
        case 11 :
            int c;
            c=Depth(T);
            printf("树的深度为%d",c);
            break;
        case 12 :
            int a;
            a=NodeCount(T);
            printf("共有%d个节点",a);
            break;
        case 13 :
            DestoryTree(T);
            break;
        }
    }
    printf("谢谢使用");
    system("pause");
	return 0;

}

operation.cpp
创建链表:

BTree* CreateBinaryTree()
{
    BTree *p;
    TElemType a;
    printf("输入元素");
    scanf("%d",&a);
    if(a==0)     //递归结束,建空树
    {
        p = NULL;
    }
    else
    {
        p = (BTree*)malloc(sizeof(BTree));
        p->data = a;  //先递后归
        p->Left  = CreateBinaryTree();  //递归创建左子树
        p->Right = CreateBinaryTree();  //递归创建右子树
    }
    return p;
}

递归遍历部分:

void PreOderTraverse1(BTree*T)//前序遍历
{
  if(T==NULL)
  {
    return;
  }
  printf("%d\t",T->data);
  PreOderTraverse1(T->Left);
  PreOderTraverse1(T->Right);
}

void InOderTravers1(BTree*T)//中序遍历
{
  if(T==NULL)
   {
    return;
   }
   InOderTravers1(T->Left);
   printf("%d\t",T->data);
   InOderTravers1(T->Right);
}

void PostOderTravers1(BTree*T)//后序遍历
{
  if(T==NULL)
   {
     return;
   }
   PostOderTravers1(T->Left);
   PostOderTravers1(T->Right);
   printf("%d\t",T->data);
}

非递归部分:

void PreOderTraverse2(BTree*T)//非递归前序遍历
{
  if (T == NULL)
		return;
	BTree* p = T;
	stack<BTree*>s;
	while (!s.empty() || p)
	{
		//边遍历边打印,并存入栈中,以后需要借助这些根节点(上一个保存的节点)进入右子树
		while (p)
		{
			printf("%d\t",p->data);
			s.push(p);
			p = p->Left;
		}
		//当p为空时,说明根和左子树都遍历完了,该进入右子树了
		if (!s.empty())
		{
			p = s.top();
			s.pop();
			p = p->Right;
		}
	}
}
void InOderTravers2(BTree*T)//非递归中序遍历
{
    //空树
	if (T == NULL)
		return;
	//树非空
    BTree*p = T;
	stack<BTree*> s;
	while (!s.empty() || p)
	{
		//一直遍历到左子树最下边,边遍历边保存根节点到栈中
		while (p)
		{
			s.push(p);
			p = p->Left;
		}
		//当p为空时,说明已经到达左子树最下边,这时需要出栈了
		if (!s.empty())
		{
			p = s.top();
			s.pop();
			printf("%d\t",p->data);
			//进入右子树,开始新的一轮左子树遍历(这是递归的自我实现)
			p = p->Right;
		}
	}
}
void PostOderTravers2(BTree*T)//后序非递归遍历
{
    /*难点在于需要判断上次访问的节点是位于
    左子树,还是右子树。若是位于左子树,则需跳过
    根节点,先进入右子树,再回头访问根节点;
    若是位于右子树,则直接访问根节点。*/
    if (T == NULL)
		return;
	stack<BTree*> s;
	//pN:当前访问节点,pL:上次访问节点
	BTree*pN, *pL;
	pN = T;
	pL = NULL;
	//先把pN移动到左子树最下边
	while (pN)
	{
		s.push(pN);
		pN = pN->Left;
	}
	while (!s.empty())
	{
		//走到这里,pN都是空,并已经遍历到左子树底端(看成扩充二叉树,则空,亦是某棵树的左孩子)
		pN = s.top();
		s.pop();
		//一个根节点被访问的前提是:无右子树或右子树已被访问过
		if (pN->Right== NULL || pN->Right == pL)
		{
			printf("%d\t",pN->data);
			//修改最近被访问的节点
			pL = pN;
		}
		/*这里的else语句可换成带条件的else if:
		else if (pCur->lchild == pLastVisit)//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈)
		因为:上面的条件没通过就一定是下面的条件满足。
		*/
		else
		{
			//根节点再次入栈
			s.push(pN);
			//进入右子树,且可肯定右子树一定不为空
			pN= pN->Right;
			while (pN)
			{
				s.push(pN);
				pN = pN->Left;
			}
		}
	}
}

层序的数组与队的实现:

void LeavelOrderTravers1(BTree*T) //层序遍历队列实现
{
    queue <BTree*> q;
    if (T!=NULL)
    {
        q.push(T);   //根节点进队列
    }

    while (q.empty() == false)  //队列不为空判断
    {
        printf("%d\t",q.front()->data);

        if (q.front()->Left != NULL)   //如果有左孩子,left入队列
        {
            q.push(q.front()->Left);
        }

        if (q.front()->Right!= NULL)   //如果有右孩子,right入队列
        {
            q.push(q.front()->Right);
        }
        q.pop();  //已经遍历过的节点出队列
    }

}

void LeavelOrderTravers2(BTree*T)//层序遍历数组实现
{
    BTree*temp[100];   //创建BTree指针类型的指针数组
    int in = 0;
    int out = 0;       //可以将in和out看成指向数组位置的两个指针
    temp[in++] = T;  //先保存二叉树根节点
    while (in > out)
    {
        if (temp[out])
        {
            printf("%d\t",temp[out]->data);
            temp[in++] = temp[out]->Left;
            temp[in++] = temp[out]->Right;
        }
        out++;
    }
}

其余功能:

void Copy(BTree*T,BTree*NT)//复制树
{                                       //error: expected unqualified-id before '{'token
    //函数名后面多加了个分号 void Copy();
  if(T==NULL)
  {
      NT=NULL;
      return;
  }
  else
  {
      NT = (BTree*)malloc(sizeof(BTree));
      NT->data=T->data;
      Copy(T->Left,NT->Left);
      Copy(T->Right,NT->Right);
  }
}


void DestoryTree(BTree*T)//销毁树
{
   if(T!=NULL)
	{
		DestoryTree(T->Left);
		DestoryTree(T->Right);
		delete T;
	}
   else
    printf("销毁完毕");
}

int Depth(BTree*T)//计算二叉树深度
{
    int m,n;
    if(T==NULL)
        return 0;
    else
    {
        m=Depth(T->Left);
        n=Depth(T->Right);
        if(m>n) return(m+1);
        else
            return(n+1);
    }
}

int NodeCount(BTree*T)//计算节点个数
{
   if(T==NULL)
   {
     return 0;
   }
   return NodeCount(T->Left)+NodeCount(T->Right)+1;
}

发布了21 篇原创文章 · 获赞 10 · 访问量 2661

猜你喜欢

转载自blog.csdn.net/weixin_42199022/article/details/90265485