Loading

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

数据表示:

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哒!

posted @ 2014-07-16 15:08  dai.sp  阅读(1071)  评论(0编辑  收藏  举报