• 二叉树的前序、中序、后序、层序遍历


    数据表示:

    1 //二叉链表存储 
    2 struct BTNode
    3 {
    4     struct BTNode *LChild;    // 指向左孩子指针
    5     ELEMENTTYPE    data;      // 结点数据
    6     struct BTNode *RChild;    // 指向右孩子指针
    7 };

    前序遍历:

     1 // 递归实现
     2 void PreorderTraversal(BTNode *BT)
     3 {
     4     if(BT!=NULL) {
     5         Print(BT->data);                                // 访问根结点
     6         PreorderTraversal(BT->LChild);                  // 前序遍历左子树
     7         PreorderTraversal(BT->RChild);                  // 前序遍历右子树
     8     }
     9 }
    10 
    11 // 非递归实现
    12 void PreorderTraversal(BTNode *BT)
    13 {
    14     InitStack(stack, treeDeepth);                       // 初始化元素为结点指针类型的栈stack,用以保存结点的指针
    15     BTNode *current = BT;                               // current指向但前要访问的结点,初始时指向根结点
    16     while(current != NULL || !EmptyStack(stack)) {      /* current为空结点且栈空,遍历结束 */
    17         if(current != NULL) {                           /* 若current不是空结点 */
    18             Print(current->data);                       // 访问current指向的结点
    19             Push(stack, current);                       // 当前结点指针current压栈
    20             current = current->LChild;                  // 使current的左孩子成为当前结点
    21         } else {                                        /* 若current指向的为空结点 */
    22             current = Pop(stack);                       // 弹出栈顶的结点指针赋给current
    23             current = current->RChild;                  // 使current的右孩子成为当前结点
    24         }
    25     }
    26 }

    中序遍历:

     1 // 递归实现
     2 void InorderTraversal(BTNode *BT)
     3 {
     4     if(BT!=NULL) {
     5         InorderTraversal(BT->LChild);                   // 中序遍历左子树
     6         Print(BT->data);                                // 访问根结点
     7         InorderTraversal(BT->RChild);                   // 中序遍历右子树
     8     }
     9 }
    10 
    11 // 非递归实现
    12 void InorderTraversal(BTNode *BT)
    13 {
    14     InitStack(stack, treeDeepth);                       // 初始化元素为结点指针类型的栈stack,用以保存结点的指针
    15     BTNode *current = BT;                               // current指向但前要访问的结点,初始时指向根结点
    16     while(current != NULL || !EmptyStack(stack)) {      /* current为空结点且栈空,遍历结束 */
    17         if(current != NULL) {                           /* 若current不是空结点 */
    18             Push(stack, current);                       // 当前结点指针current压栈
    19             current = current->LChild;                  // 使current的左孩子成为当前结点
    20         } else {                                        /* 若current指向的为空结点 */
    21             current = Pop(stack);                       // 弹出栈顶的结点指针赋给current
    22             Print(current->data);                       // 访问current指向的结点
    23             current = current->RChild;                  // 使current的右孩子成为当前结点
    24         }
    25     }
    26 }

    后序遍历:

     1 // 递归实现
     2 void PostorderTraversal(BTNode *BT)
     3 {
     4     if(BT!=NULL) {
     5         PostorderTraversal(BT->LChild);                 // 后序遍历左子树
     6         PostorderTraversal(BT->RChild);                 // 后序遍历右子树
     7         Print(BT->data);                                // 访问根结点
     8     }
     9 }
    10 
    11 // 非递归实现
    12 void PostorderTraversal(BTNode *BT)
    13 {
    14     InitStack(stack, treeDeepth);                       // 初始化元素为结点指针类型的栈stack,用以保存结点的指针
    15     BTNode *current = BT;                               // current指向但前要访问的结点,初始时指向根结点
    16     Push(stack, current);                               // 当前结点指针current压栈
    17     while(current->LChild != NULL) {                    /* 从当前结点出发,逐步找到二叉树左边结点并依次进栈 */
    18         current = current->LChild;
    19         Push(stack, current);
    20     }
    21     while(!EmptyStack(stack)) {                         /* 一直进行到栈空为止,整棵二叉树遍历完成 */
    22         current = Pop(stack);                           // 栈顶结点退栈作为当前结点
    23         if(current < 0) {                       /* 若当前结点指针标志为“负”,表示该结点的右子树已遍历完,应该访问该结点 */ 
    24             current = -current;                 /******* 对指针加正负号,OK,学习了,竟然这样子来标识 *******/
    25             Print(current->data);
    26         } else {                                /* 若当前结点标志为“正”,表示该结点的左子树已遍历完,应该遍历其右子树 */
    27             Push(stack, -current);                      // 对当前结点指针加左子树已遍历标志并入栈
    28             if(current->RChild != NULL) {               // 若当前结点有右子树,以右孩子作为当前结点,从它出发做后序遍历
    29                 current = current->RChild;
    30                 Push(stack, current);
    31                 while(current->LChild != NULL) {
    32                     current = current->LChild;
    33                     Push(stack, current);
    34                 }
    35             }
    36         }
    37     }
    38 }
    39 
    40 /*
    41  * 非递归实现  双栈
    42  * 思路:
    43  *  按“左-右-根”顺序遍历二叉树的顺序与按“根-右-左”顺序遍历二叉树的顺序正好相反
    44  *  所以,将按“根-右-左”顺序遍历二叉树的结点依次压入postStack栈中,遍历完后再
    45  *  输出postStack栈中所有的元素结点所对应的值即是按“左-右-根”顺序遍历二叉树的顺序
    46  */
    47 void postorderTraversal(struct BTreeNode *root)
    48 {
    49     initStack(tempStack, STACKSIZE);           // 初始化元素为结点类型指针的栈tempStack,用以保存刚访问过的结点,利于回溯
    50     initStack(postStack, BTREESIZE);           // 初始化元素为结点类型指针的栈postStack,用以保存按“根-右-左”顺序依次访问的结点
    51 
    52     struct BTreeNode *currentNode = root;                   // currentNode指向当前要访问的结点,初始时指向根结点
    53     while(currentNode != NULL || !isEmpty(tempStack)) {     /* 当currentNode为空结点其tempStack栈空,遍历结束 */
    54         if(currentNode != NULL) {                           // 若currentNode指向的不是空结点
    55             push(postStack, currentNode);                   // currentNode结点压入postStack栈中
    56             push(tempStack, currentNode);                   // currentNode结点压入tempStack栈中
    57             currentNode = currentNode->rightChild;          // 使currentNode指向当前结点的右孩子结点
    58         } else {                                            // 若currentNode不为空结点    
    59             currentNode = pop(tempStack);                   // 弹出tempStack栈顶结点指针并赋给currentNode指针
    60             currentNode = currentNode->LChild;              // 是使currentNode指向当前结点的左孩子结点
    61         }
    62     }
    63     outStack(postStack);
    64 }

    层序遍历:

     1 /*
     2  * 层序遍历二叉树
     3  */
     4 void levelOrderTraversal(struct BTreeNode *root)
     5 {
     6     initQueue(queue, QUEUESIZE);                        // 初始化元素为二叉树结点指针类型的队列
     7     if(root != NULL)                                    // 若二叉树不为空,根结点指针入队
     8         enQueue(queue, root);
     9 
    10     struct BTreeNode currentNode = NULL;
    11     while(!isEmpty(queue)) {                            /* 直到队列为空,遍历结束 */
    12         currentNode = outQueue(queue);                  // 队头元素出列
    13         print(currentNode->data);                       // 访问当前结点信息
    14         if(currentNode->LChild != NULL)                /* 若当前结点有左孩子,则将其入队 */
    15             enQueue(queue, currentNode->LChild);
    16         if(currentNode->rightChild != NULL)             /* 若当前结点有右孩子,则将其入队 */
    17             enQueue(queue, currentNode->rightChild);
    18     }
    19 }

    二叉树遍历方法的简单应用:

     1 /*
     2  * 前序遍历应用:输出二叉树   递归实现
     3  */
     4 void outBTree(struct BTreeNode *root)
     5 {
     6     if(root != NULL) {                                                  // 若二叉树为空
     7         print(root->data);                                              // 输出根结点值
     8         if(root->LChild != NULL || root->rightChild != NULL) {         // 有左子树或右子树
     9             print("(");                                        // 输出左括号
    10             outBT(root->LChild);                              // 输出左子树
    11             print(",");                                        // 输出左右子树的分隔符
    12             if(root->rightChild != NULL)                       // 若有右子树
    13                 outBTree(root->rightChild);                    // 输出右子树            
    14             print(")");                                        // 输出右括号
    15         }
    16     }
    17 }
    18 
    19 /*
    20  * 前序遍历应用:查找二叉树中是否存在指定值   递归实现
    21  */
    22 bool findBTree(struct BTreeNode *root, ElementType item)
    23 {
    24     if(root == NULL) {                                          // 二叉树为空,则返回false
    25         return false;
    26     } else {
    27         if(root->data == item) {                                // 若根结点为所找结点,返回true
    28             return true;
    29         } else {
    30             if(findBTree(root->LChild, item) == true) {        // 递归查找当前结点的左子树,若找到,返回true
    31                 return true;
    32             }
    33             if(findBTree(root->rightChild, item) == true) {     // 递归查找当前结点的右子树,若找到,返回false
    34                 return true;
    35             }
    36             return false;                                       // 若左右子树都未找到,返回false
    37         }
    38     }
    39 }
    40 
    41 /*
    42  * 后序遍历应用:计算二叉树的深度     递归实现
    43  */
    44 int getBTreeDeepth(struct BTreeNode *root)
    45 {   
    46     if(root == NULL) {                                                      // 二叉树为空,返回深度为0
    47         return 0;
    48     } else {
    49         int deepth_1 = getBTreeDeepth(root->LChild);                       // 递归求左子树的深度
    50         int deepth_2 = getBTreeDeepth(root->RChild);                       // 递归求右子树的深度
    51         return (deepth_1 > deepth_2) ? (deepth_1 + 1) : (deepth_2 + 1);     // 求出树的深度并返回
    52     }
    53 }
    54 
    55 /*
    56  * 后序遍历应用:清空二叉树   递归实现
    57  */
    58 void clearBTree(struct BTreeNode *root)
    59 {
    60     /* 若二叉树为空树,则结束递归 */
    61     if(root != NULL) {
    62         clearBTree(root->LChild);        // 递归删除根结点的左子树
    63         clearBTree(root->rightChild);     // 递归删除根结点的右子树
    64         delete root;                 // 释放根结点
    65         root = NULL;                // 将根结点指针置空
    66     }
    67 }

    OK哒!

  • 相关阅读:
    django模板使用
    django视图的定义
    字符串逆序
    Django 中Admin站点的配置
    Django模型Model的定义
    Django安装部署
    Linux常用命令
    深拷贝,浅拷贝
    lambda 表达式 (匿名函数)
    生成器与迭代器
  • 原文地址:https://www.cnblogs.com/gotodsp/p/3848751.html
Copyright © 2020-2023  润新知