zoukankan      html  css  js  c++  java
  • 如何用栈遍历二叉树

    摘自:https://blog.csdn.net/cocoiehl/article/details/80959143

          https://bbs.csdn.net/topics/391882020

    (只是为了方便自己复习)

     

    一般我们遍历二叉树的时候用的是递归,用递归实现比较简单,代码如下:

    /****************
    基于递归实现后序遍历,
    *****************/
    void PostOrderTraverse(NODE* pRoot) {
    	if (pRoot == NULL) {
    		return;
    	}
    	else {
    		PostOrderTraverse(pRoot->pLeft);
    		PostOrderTraverse(pRoot->pRight);
    		printf("%c", pRoot->chValue);
    	}
    	return;
    }
    

    通过改变printf语句的位置便可以实现前序和中序遍历。

    下面我们来看看如何基于栈实现二叉树的遍历,可以把二叉树分为root,left,right三个部分
    前序遍历的次序为root,left,right;
    中序遍历的次序为left,root,right;
    后序遍历的次序为left,right,root;
    先讨论前序遍历和中序遍历,显然可以通过下面的步骤实现
    1.不断将左子树入栈,直到左子树为空
    2.不断出栈,直到出栈元素的右子树不为空
    3.如果栈不为空或当前根结点不为空,重复步骤1和2
    前序遍历是在步骤1中将入栈的树的根结点输出,而中序则是在步骤2中将出栈的树的根结点输出
    代码如下:

    /****************
    基于栈实现前序和中序遍历
    *****************/
    void OrderTraverseByStack(NODE* pRoot) {
    	NODE* Stack[1000];
    	int top = 0;
    	while (top > 0 || pRoot != NULL) {
    		for (; pRoot != NULL; pRoot = pRoot->pLeft) {
    			Stack[top++] = pRoot;
    			//前序遍历
    			//printf("%c",pRoot->chValue);
    		}
    		for (; pRoot == NULL&&top > 0; pRoot = pRoot->pRight) {
    			pRoot = Stack[--top];
    			//中序遍历
    			//printf("%c", pRoot->chValue);
    		}
    	}
    }
    

    最后要如何基于栈实现二叉树的后序遍历呢?通过观察可以发现
    前序遍历的次序为root,left,right;
    后序遍历的次序为left,right,root;
    将前序遍历的left和right调换,在倒过来输出,便可以实现后序遍历!
    因此我们可以通过修改一下上面的代码实现后序遍历,方法如下:
    1,将前序遍历代码中的left 和right 对调,并数据存在栈S中。
    2,前序遍历完后,将栈S中的数据逐个出栈并打印即可。
    代码如下:

    /****************
    基于栈实现后序遍历
    *****************/
    void PostOrderTraverseByStack(NODE* pRoot) {
    	NODE *StackA[1000],*StackB[1000];
    	int topA = 0,topB = 0;
    	while (topA > 0 || pRoot != NULL) {
    		for (; pRoot != NULL;pRoot = pRoot->pRight) {
    			StackA[topA++] = pRoot;
    			StackB[topB++] = pRoot;
    		}
    		for (; pRoot == NULL&&topA > 0; pRoot = pRoot->pLeft) {
    			pRoot = StackA[--topA];
    		}
    	}
    	while (topB > 0) {
    		printf("%c", StackB[--topB]->chValue);
    	}
    }
    


    下面是测试代码:

    #include<stdio.h>
    #include<stdlib.h>
     
    #define TREELEN 6
     
    struct NODE {
        NODE* pLeft;
        NODE* pRight;
        char chValue;
    };
     
    void ReBuild(char* pPreOrder,char* pInOrder,int nTreeLen,NODE** pRoot) {
        if (pPreOrder == NULL || pInOrder == NULL) {
            return;
        }
        NODE* pTemp =(NODE* )malloc(sizeof(NODE));
        pTemp->chValue = *pPreOrder;
        pTemp->pLeft = NULL;
        pTemp->pRight = NULL;
        if (*pRoot == NULL) {
            *pRoot = pTemp;
        }
        if (nTreeLen == 1) {
            return;
        }
        char* pOrgInOrder = pInOrder;
        char* pLeftEnd = pInOrder;
        int nTempLen = 0;
        while (*pPreOrder != *pLeftEnd) {
            if (pPreOrder == NULL || pLeftEnd == NULL) {
                return;
            }
            nTempLen++;
            if (nTempLen > nTreeLen) {
                break;
            }
            pLeftEnd++;
        }
        int nLeftLen = 0;
        nLeftLen = (int)(pLeftEnd - pOrgInOrder);
        int nRightLen = 0;
        nRightLen = nTreeLen - nLeftLen - 1;
        if (nLeftLen > 0) {
            ReBuild(pPreOrder+1, pInOrder, nLeftLen, &((*pRoot)->pLeft));
        }
        if (nRightLen > 0) {
            ReBuild(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen +1, nRightLen, &((*pRoot)->pRight));
        }
    }
     
    /****************
    基于递归实现后序遍历,
    *****************/
    void PostOrderTraverse(NODE* pRoot) {
        if (pRoot == NULL) {
            return;
        }
        else {
            PostOrderTraverse(pRoot->pLeft);
            PostOrderTraverse(pRoot->pRight);
            printf("%c", pRoot->chValue);
        }
        return;
    }
     
    /****************
    基于栈实现前序和中序遍历
    *****************/
    void OrderTraverseByStack(NODE* pRoot) {
        NODE* Stack[1000];
        int top = 0;
        while (top > 0 || pRoot != NULL) {
            for (; pRoot != NULL; pRoot = pRoot->pLeft) {
                Stack[top++] = pRoot;
                //前序遍历
                //printf("%c",pRoot->chValue);
            }
            for (; pRoot == NULL&&top > 0; pRoot = pRoot->pRight) {
                pRoot = Stack[--top];
                //中序遍历
                printf("%c", pRoot->chValue);
            }
        }
    }
     
    /****************
    基于栈实现后序遍历
    *****************/
    void PostOrderTraverseByStack(NODE* pRoot) {
        NODE *StackA[1000],*StackB[1000];
        int topA = 0,topB = 0;
        while (topA > 0 || pRoot != NULL) {
            for (; pRoot != NULL;pRoot = pRoot->pRight) {
                StackA[topA++] = pRoot;
                StackB[topB++] = pRoot;
            }
            for (; pRoot == NULL&&topA > 0; pRoot = pRoot->pLeft) {
                pRoot = StackA[--topA];
            }
        }
        while (topB > 0) {
            printf("%c", StackB[--topB]->chValue);
        }
    }
     
    int main() {
        NODE* pRoot = NULL;
        char pre[TREELEN] = { 'a','b','d','e','c','f' };
        char in[TREELEN] = { 'd','b','e','a','f','c' };
        ReBuild(pre, in, TREELEN, &pRoot);
        printf("
    通过栈实现的中序遍历结果:
    ");
        OrderTraverseByStack(pRoot);
        printf("
    通过递归实现的后序遍历结果:
    ");
        PostOrderTraverse(pRoot);
        printf("
    通过栈实现的后序遍历结果:
    ");
        PostOrderTraverseByStack(pRoot);
        getchar();
        return 0;
    }
    

      

  • 相关阅读:
    WebFrom与MVC异同
    MVC解决WebFrom的缺点
    转载ORM--EF框架
    转载 HashSet用法 合交并差
    用户管理模块数据库设计
    外键的增删改查练习
    索引:如何让主键不自动创建聚集索引???
    SQL-类型转换函数
    SQL-union
    SQL字符串函数
  • 原文地址:https://www.cnblogs.com/myhnb/p/11537506.html
Copyright © 2011-2022 走看看