二叉树相关概念及创建

二叉树的一些性质:

度就是一个节点的分支数
对于任何一个 二叉树,如 果其叶节点的个数为n0,度为2的非叶节点个数是n2,则有n0=n2+1
(n0+n1+n2=2*n2+n1+1)——-(n0=n2+1);
度为1的非叶子节点个数为n1;
节点个数为n0+n1+n2;
边的个数为2*n2+n1;
节点的个数为:边的个数+1;
具有n个节点的完全二叉树的深度K为log2(n+1)向上取整。
一个具有n个节点的完全二叉树,如果按照从上至下从左到右的顺序对所有节点从0开始编号,则对于序号为i的节点有:

    1)若>0,双亲信号为:(i-1)/2;
            i=0;i为根节点编号,没有双亲
    2)若2i+1<n,左孩子编号:2i+1,否则没有左孩子
    3)若2i+2<n,右孩子序号:2i+2,否则无右孩子 

二叉树形如下图:

1、构建一个二叉树

树的结构体 :

typedef struct BinaryTreeNode//树的结构体
{
     Datatype data;
     struct BinaryTreeNode* LeftTree;
     struct BinaryTreeNode* RightTree;
}BTNode;

思想:创建一棵树,首先应该创建一个 新的树的根节点,遍历一个 数组,数组 的内容就是树的数据,当数组中为“#”时,代表是空树,使用递归的方法依次创建左子树和右子书。

代码如下:

BTNode* CreatTree(Datatype a[],int size,int* index)
{
     BTNode* pRoot = (BTNode*)malloc(sizeof(BTNode));
     assert(index);
     if((*index) >= size)//表示已经将数组遍历完了
     {
          return NULL;
     }
     if (a[*index] == '#')//代表子树为空的情况
     {
          (*index)++;
          return NULL;
     }
     //BTNode* pRoot = (BTNode*)malloc(sizeof(BTNode));
     pRoot->data = a[*index];
     (*index)++;
     pRoot->LeftTree = CreatTree(a, size, index);
     pRoot->RightTree = CreatTree(a, size, index);

     return pRoot;
}

2、前序遍历

递归方式
void Prevorder(BTNode* pRoot)//前序遍历
{
     if (pRoot == NULL)
     {
          return ;
     }
     printf("%c-", pRoot->data);//输出根节点
     Prevorder(pRoot->LeftTree);//递归左子树
     Prevorder(pRoot->RightTree);//递归右子树
}
非递归方式 :
void UnPrevorder(BTNode* pRoot)//前序遍历非递归
{
     Stack S;
     BTNode* pTop;
     StackInit(&S);//栈的初始化
     BTNode*  pCur=pRoot;
     while (!StackEmpty(&S) || (pCur != NULL))
     {
          while (pCur != NULL)
          {
              printf("%c ", pCur->data);//输出根节点
              StackPush(&S, pCur);//压栈,这个一定要注意,并不是单纯的把数据压入栈,而是将节点压入栈
              pCur = pCur->LeftTree;//继续寻找左子树,直到栈为空(遍历完成)或者pCur=NULL(所有的左子树遍历完成)
          }//左子树为空时开始寻找右子树
          pTop = Top(&S);
          StackPop(&S);
          pCur = pTop->RightTree;
     }
}

3、中序遍历

递归:
void Inorder(BTNode* pRoot)//中序遍历
{
     if (pRoot == NULL)
     {
          return NULL;
     }
     Inorder(pRoot->LeftTree);
     printf("%c-", pRoot->data);
     Inorder(pRoot->RightTree);
}
非递归:
void UnInorder(BTNode* pRoot)//中序遍历非递归
{
     Stack S;
     BTNode* pTop;
     StackInit(&S);//栈的初始化
     BTNode*  pCur = pRoot;
     while (!StackEmpty(&S) || (pCur != NULL))
     {
          while (pCur != NULL)
          {
              StackPush(&S, pCur);
              pCur = pCur->LeftTree;
          }
          pTop = Top(&S);
          StackPop(&S);
          printf("%c ", pTop->data);
          pCur = pTop->RightTree;
     }
}

4、后序遍历

递归
void Postorder(BTNode* pRoot)//后序遍历
{
     if (pRoot == NULL)
     {
          return NULL;
     }
     Postorder(pRoot->LeftTree);
     Postorder(pRoot->RightTree);
     printf("%c-", pRoot->data);
}
非递归:
void UnPostorder(BTNode* pRoot)//后序遍历非递归
{
     Stack S;
     BTNode* pTop;
     StackInit(&S);//栈的初始化
     BTNode*  pCur = pRoot;
     BTNode* Last = NULL;
     while (!StackEmpty(&S) || (pCur != NULL))//遍历完左子树
     {
          while (pCur != NULL)
          {
              StackPush(&S, pCur);
              pCur = pCur->LeftTree;
          }
          pTop = Top(&S);
          if (pTop->RightTree == NULL || pTop->RightTree==Last)
          {//若栈顶元素的右子树为空,那么就可以输出这个节点的数据,再将这个节点赋给last,、
              //如果一个节点的右字数=last,那个这个节点就可以输出
              printf("%c ", pTop->data);
              StackPop(&S, pTop);
              Last = pTop;
              continue;
          }
          pCur = pTop->RightTree;
     }
}

5、层序遍历

void UnLevelorder(BTNode* pRoot)//层序遍历非递归
{
     Quene q;
     BTNode* FrontNode;
     if (pRoot == NULL)
     {
          return NULL;
     }
     QueneInit(&q);
     QuenePush(&q, pRoot);
     while (!QueneEmpty(&q))
     {
          FrontNode = QueneFront(&q);
          QuenePop(&q);
          printf("%c ", FrontNode->data);
          if (FrontNode->LeftTree != NULL)
          {
              QuenePush(&q, pRoot->LeftTree);
          }
          if (FrontNode->RightTree != NULL)
          {
              QuenePush(&q, pRoot->RightTree);
          }
     }
     printf("\n");
}

6、求节点的数量

int CountOfNodeone(BTNode* pRoot)//求节点数量
{
     //static int n = 0;
     if (pRoot == NULL)
     {
          return NULL;
     }
     n++;
     CountOfNodeone(pRoot->LeftTree);
     CountOfNodeone(pRoot->RightTree);
     return n;
}
划分成子问题也可以解决
int CountOfNodetwo(BTNode* pRoot)//求节点数量,分解为子问题
{
     if (pRoot==NULL)
     {
          return NULL;
     }
     return CountOfNodetwo(pRoot->LeftTree) + CountOfNodetwo(pRoot->RightTree) + 1;
}

7、求叶子节点的个数

int CountOfLeafNode(BTNode* pRoot)//求叶子节点的个数
{
     if (pRoot == NULL)
     {
          return NULL;
     }
     if ((pRoot->LeftTree)== NULL&&(pRoot->RightTree== NULL))
     {
          return 1;
     }
     return CountOfLeafNode(pRoot->LeftTree) + CountOfLeafNode(pRoot->RightTree);

}

8、求第k层节点的个数

int CountKNode(BTNode* pRoot,int k)//求第K层节点的数量
{
     if (pRoot == NULL&&k==1)
     {
          return NULL;
     }
     if (pRoot != NULL&&k == 1)
     {
          return 1;
     }
     return CountKNode(pRoot->LeftTree, k - 1) + CountKNode(pRoot->RightTree, k - 1);
}

9、求树的深度

int DepthOfNode(BTNode* pRoot)//求一棵树的高度
{
     if (pRoot == NULL)
     {
          return NULL;
     }
     int left = DepthOfNode(pRoot->LeftTree);
     int right = DepthOfNode(pRoot->RightTree);
     return Max(left, right)+1;
}

10、查找某一个节点

BTNode* FindTreeNode(BTNode* pRoot, Datatype x)
{
     if (pRoot == NULL)
     {
          return NULL;
     }
     if (pRoot->data == x)
     {
          return pRoot;
     }
     BTNode* FoundNode;
     FoundNode=FindTreeNode(pRoot->LeftTree, x);
     if (FoundNode != NULL)
     {
          return FoundNode;
     }
     return FindTreeNode(pRoot->RightTree, x);
}

11、测试函数

test()
{
     char arr[] = { 'A', 'B', 'D', '#', '#','#','C', 'E', '#','#', 'F' };
     int i = 0;
     int ret = 0;
     int len = sizeof(arr) / sizeof(arr[0]);
     BTNode* Node;
     BTNode* pRoot = (BTNode*)malloc(sizeof(BTNode));
     pRoot = CreatTree(arr, len, &i);
     Prevorder(pRoot);
     printf("\n");
     UnPrevorder(pRoot);
     printf("\n");
     Inorder(pRoot);
     printf("\n");
     UnInorder(pRoot);
     printf("\n");
     Postorder(pRoot);
     printf("\n");
     UnPostorder(pRoot);
     printf("\n");
     ret = CountOfNodetwo(pRoot);
     printf("层序遍历:\n");
     UnLevelorder(pRoot);
     printf("节点总个数为:%d\n", ret);
     printf("叶子节点的个数为:%d\n", CountOfLeafNode(pRoot));
     printf("第%d层节点的个数为:%d\n",3,CountKNode(pRoot, 3));
     printf("该树的深度为:%d\n", DepthOfNode(pRoot));
     Node = FindTreeNode(pRoot, 'F');
     if (Node == NULL)
     {
          printf("没有找到!\n");
     }
     else
     {
          printf("数据为:%c", Node->data);
     }

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值