二叉树

来源:互联网 发布:php资源网源码 编辑:程序博客网 时间:2024/04/30 10:13

一.关于树的几个重要概念

       1). :是指节点拥有的子树数。
       2). 深度/高度:从根节点到目的节点x的一条简单路径的长度称为x的深度/高度。国内一般把根节点的高度算为1,而国外有些把根节点的高度算为0,因此计算起来会有差异。

     

     对于4这个节点,度为1,深度/高度为2或3,整个树的高度/深度为3或4。

二.二叉树基本性质

      二叉树定义由n个节点组成(n>=0),构成空树,或者由两棵互不相交的称为左子树和右子树构成。

      二叉树基本性质: 

            1> 在二叉树第i层最多有2^(i-1)个节点(i>=1)。
            2> 深度为k的二叉树最多有2^k-1个节点(k>=1)。
            3> 对于任何一棵二叉树T,终端节点数为n0,度为2的节点数为n2则n0=n2 + 1。
            4> 具有n个节点的完全二叉树的深度为[log2n] + 1,
            5> 如果对一棵有n个节点的完全二叉树(深度为[log2n] + 1)的节点按层序编号,对任一节点i(1<=i<=n)有:
              (1). 如果i=1,则i是根节点,无双亲;否则其双亲是[i/2].
              (2). 如果2i>n,则节点i无左孩子(节点i为叶节点);否则左孩子为2i.
              (3). 如果2i+1>n,则节点i无右孩子(节点i为叶子节点);否则右孩子为2i+1.

三.二叉树基本操作

     1>数据结构定义

typedef struct tagBinTreeNode{     void* value;     struct tagTreeNode * left_child;     struct tagTreeNode * right_child;}BinTreeNode;
       2>二叉树的遍历是指从根节点出发,按造一定次序,访问二叉树的所有节点,使得每个节点被访问一次。D代表根节点,L代表左孩子,R代表右孩子。
       (1).前序遍历,DLR,即先访问根节点,再前序遍历左子树和右子树。
         (2).中序遍历,LDR,即从根节点开始,中序遍历根节点的左子树然后访问根节点,最后中序遍历根节点的右子树。
         (3).后序遍历,LRD,从左到右先子叶后节点的方式遍历访问左右子树,最后是根节点。
         (4).层序遍历,从根节点开始逐层向下遍历,同一层从左到右逐个访问。

前序遍历算法:

void PreOrderTraverse(BinTreeNode *pstNode){if(pstNode == NULL){return;}printf("%c", (char)(pstNode->value));PreOrderTraverse(pstNode->left_child);PreOrderTraverse(pstNode->right_child);}

中序遍历算法:

void InOrderTraverse(BinTreeNode *pstNode){if(pstNode == NULL){return;}PreOrderTraverse(pstNode->left_child);printf("%c", (char)(pstNode->value));PreOrderTraverse(pstNode->right_child);}

后序遍历算法:

void PostOrderTraverse(BinTreeNode *ppstNode){if(pstNode == NULL){return;}PreOrderTraverse(pstNode->left_child);PreOrderTraverse(pstNode->right_child);printf("%c", (char)(pstNode->value));}
层序遍历:
void LerverOrderTraverse(BinTreeNode *pstNode){if(pstNode == NULL){return;}printf("%c", (char)(pstNode->value));PreOrderTraverse(pstNode->right_child);PreOrderTraverse(pstNode->left_child);}

3>二叉树的建立

    假设有这样一个二叉树:

 

     我们可以根据前序中序和后序的方式建立一个二叉树,约定输入*表示空节点。假设一个二叉树的前序遍历输出为:AB*D**C**,中序为:*B*D*A*C*,可以得出中序建立二叉树:
void InOrderCreateBinTree(struct tagBinTreeNode **ppstNode){char chr;scanf("%c", &chr);if(chr == '*'){*ppstNode = NULL;}else{(*ppstNode) = (struct tagBinTreeNode*)malloc(sizeof(struct tagBinTreeNode));if((*ppstNode) == NULL){exit(-1);}memset((*ppstNode), 0x00, sizeof(struct tagBinTreeNode));InOrderCreateBinTree(&(*ppstNode)->left_child); //创建左子树(*ppstNode)->value = chr; //构造根节点InOrderCreateBinTree(&(*ppstNode)->right_child); //创建右子树}}
*注意, 虽然说是中序建立二叉树,但是字符的输入顺序应该按照前序列输入方式,设想如果先构造了左子树那么是无法退回父节点的。

四:测试

int main(int arrc, char* argv[]){struct tagBinTreeNode *pstNode = NULL;InOrderCreateBinTree(&pstNode);printf("\n前序输出:");PreOrderTraverse(pstNode);printf("\n中序输出:");InOrderTraverse(pstNode);printf("\n后序输出:");PostOrderTraverse(pstNode);printf("\n层序输出:");LevelOrderTraverse(pstNode);printf("\n");return (0);}
输出:
lc@lc-Lenovo:~/work/ProgramTrain$ ./a.out AB*D**C**前序输出:ABDC中序输出:BDAC后序输出:BDCA层序输出:ACBD

原创粉丝点击