二叉樹遍曆:遞迴方法與非遞迴方法——遞迴程式修改為非遞迴的方法

來源:互聯網
上載者:User

前天去美團面試,二面基本一路順風,後來,碰到一個用非遞迴的方法求解二叉樹高度,並要求現場寫程式,一下就卡住了,非常不爽。這兩天把這個部分惡補了一下,總結了一下思路如下。

1、考慮清楚解題類似於遍曆中的前序 or 中序 or 後續;

2、考慮清楚在遞迴程式中,每次會有哪些內容需要進棧:節點本身、返回地址(用於告訴程式返回後應該從何處執行)、局部變數、傳回值。

下面先上代碼,並比較得出思路。

首先,我們看一下先序遍曆的遞迴和非遞迴程式:

void PreTraverse(CNode *subTree, bool (*Visit)(CNode *)){if (subTree){Visit(subTree);PreTraverse(subTree->lchild, Visit);PreTraverse(subTree->rchild, Visit);}}void PreTraverseNonRecursive(CNode *subTree, bool (*Visit)(CNode *)) // 你會把這個函數按照後邊的形式簡化嗎^^這個函數來源於網路,個人認為寫的比較繁瑣。你可以使用三個case簡化。{std::stack<CNode*> s;CNode *t = subTree;s.push(t);while (!s.empty()){while (!s.empty()) // go left until the most left child{t = s.top(); // notice: without pop!!if (!t)break;Visit(t);s.push(t->lchild);}s.pop(); // pop null pointerif (!s.empty()) // right child{t = s.top(); s.pop();s.push(t->rchild);}}}

其次,中序遍曆:

void InTraverse(CNode *subTree, bool (*Visit)(CNode *)){if (subTree){InTraverse(subTree->lchild, Visit);Visit(subTree);InTraverse(subTree->rchild, Visit);}}void InTraverseNonRecursiveVer2(CNode *subTree, bool (*Visit)(CNode *))    {        class CPostNode        {        public:            CNode* pNode;            int flag;            CPostNode(CNode *n, int i)            {                pNode = n;                flag = i;            };        };        std::stack<CPostNode> s;        CPostNode t(subTree, 1);        s.push(t);        while (!s.empty())        {            t= s.top(); s.pop();            switch(t.flag)            {            case 1:                t.flag = 2;                s.push(t);                if (t.pNode->lchild)                {                    s.push(CPostNode(t.pNode->lchild, 1));                }                break;            case 2:                Visit(t.pNode);                if (t.pNode->rchild)                {                    s.push(CPostNode(t.pNode->rchild, 1));                }                break;            case 3: // unable to run to here for in-traverse.                break;            }        }    } 

再然後,是後續遍曆:

void PostTraverse(CNode *subTree, bool (*Visit)(CNode *)){if (subTree){PostTraverse(subTree->lchild, Visit);PostTraverse(subTree->rchild, Visit);Visit(subTree);}}void PostTraverseNonRecursive(CNode *subTree, bool (*Visit)(CNode *)){class CPostNode{public:CNode* pNode;int flag;CPostNode(CNode *n, int i){pNode = n;flag = i;};};std::stack<CPostNode> s;CPostNode t(subTree, 1);s.push(t);while (!s.empty()){t = s.top(); s.pop(); // notice: pop() here!!switch(t.flag){case 1:t.flag = 2;s.push(t);if (t.pNode->lchild){s.push(CPostNode(t.pNode->lchild, 1));}break;case 2:t.flag = 3;s.push(t);if (t.pNode->rchild){s.push(CPostNode(t.pNode->rchild, 1));}break;case 3:Visit(t.pNode);//s.pop();break;}}}

最後,也就是把我難倒的,非遞迴法求樹的高度:

int GetSubTreeDepth(CNode *subTree){if (!subTree)return 0;return std::max<int>(GetSubTreeDepth(subTree->lchild), GetSubTreeDepth(subTree->rchild)) + 1;}int GetSubTreeDepthVer2(CNode *subTree){class CStackNode{public:CNode* pNode;int flag;int depth;CStackNode(CNode *n, int i, int d){pNode = n;flag = i;depth = d;};};std::stack<CStackNode> s;CStackNode t(subTree, 1, 1);s.push(t);while (!s.empty()){t = s.top(); s.pop();switch (t.flag){case 1:t.flag = 2;s.push(t);if (t.pNode->lchild){s.push(CStackNode(t.pNode->lchild, 1, 1));}break;case 2:t.flag = 3;s.push(t);if (t.pNode->rchild){s.push(CStackNode(t.pNode->rchild, 1, 1));}break;case 3:if (s.empty())return t.depth;CStackNode t3 = s.top(); s.pop();t3.depth = std::max<int>(t3.depth, t.depth + 1);s.push(t3);break;}}return t.depth;}

從上面的例子中,我們能清晰的看到解題的思路:用flag來標記我們訪問該節點第幾次,不同的次數意味著要做不同的事情,所以在程式中有不同的case執行著不同的代碼。

另外,一個需要關注的地方是,在求樹的高度時,case 3中需要首先判斷s是否為空白,若為空白則可直接返回高度了~

所有代碼為本人花了一天的時間完成,引用請註明出處,謝謝~

xjs.xjtu@gmail.com

2012-10-24

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.