通过树的递归实现前序遍历的例子,深入理解递归的执行原理
どの章に基づいて構築されたこの章:
Cデータ構造とアルゴリズム - 連結の基礎 - 木02:バイナリツリートラバーサルの確立と異なります
この章を理解した後も参照してください:
Cデータ構造とアルゴリズム - ベースの仕上げ - 木04:回路図 - 先行順木
Cデータ構造及びアルゴリズム - ベースの仕上げ - ツリー05:回路図 - ツリーの順序トラバーサル
再帰関数は、グラフィックの前順走査を行い、
コードは以下の通りであります:
//前序遍历,递归实现
void PreorderTraversal(BinTree BT)
{
if (BT == NULL) return;
printf(" %c", BT->data);
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
return;
}
再帰の原理を示します。
元のバイナリツリー:
1.最初のステップは、PreorderTraversalを呼び出しノードA、ノードトラバーサル完了を印刷します。
空ではないので、前記第1のステップは、プリントノードB、ノードBトラバーサル完了、第2工程を呼び出しを開始し、PreorderTraversal(BT->左)を行い、印刷ノードを呼び出します。
前記第2ステップでは、空ではないので、その後の印刷ノードD、ノードDトラバーサル完了、第3工程で始まる、PreorderTraversal(BT->左)を行い、印刷ノードを呼び出します。
空ではないので、ノードを印刷した後4.第3のステップは、次に、第四のステップで始まる、プリントノードH、ノードHトラバーサル完了をPreorderTraversal(BT->左)を行います。
前記第4ステップノードを印刷した後、次いで、空であるように、それが呼び出しPreorderTraversal第四工程(BT->左)、通話開始に戻り、第五のステップで始まる、PreorderTraversal(BT->左)を呼び出しますPreorderTraversal(BT->右)、BT-ため>右第四工程への即時復帰して、空である、この時間の終わりまで第四工程、第三工程に戻ります。第3のステップは、右は空です> BT-による、PreorderTraversal(BT->右)を開始したリターンはすぐに、また完成した第三ステップは、第二のステップは、呼び出し元に返され、第二段階はPreorderTraversal(BT->右)を開始しました空ではないので、ノードEは、Eノードトラバーサル完了の印刷を開始、との第3工程を開始します。
6.新的第三步调用打印结点后,开始执行PreorderTraversal(BT->Left),由于BT->Left 为空,立刻返回至第三步,第三步开始执行PreorderTraversal(BT->Right),开始执行第四步调用,由于不为空,打印 I 结点,I 结点遍历完成。
7.第四步打印结点后,开始执行PreorderTraversal(BT->Left),由于BT->Left为空,返回至第三步,这个第四步执行完毕,此时第三步执行到函数末尾,执第三步行完毕,返回至第二步,此时的第二步也执行到末尾,第二步执行完毕,返回至第一步,此时第一步已经调用了PreorderTraversal(BT->Left)打印了B结点,开始执行PreorderTraversal(BT->Right),新的第二步调用,由于BT->Right不为空,开始打印C结点,C结点遍历完成。
8.新的第二步调用打印结点后,开始执行PreorderTraversal(BT->Left),开始第三步调用,由于不为空,开始打印结点F,F结点遍历完成。
9.第三步调用打印完毕后,开始执行PreorderTraversal(BT->Left),由于为空,立刻返回,开始执行PreorderTraversal(BT->Right),由于为空。立刻返回,第三步执行到末尾,返回至第二步,第二步开始执行PreorderTraversal(BT->Right),开始新的第三步调用,由于BT->Right 不为空,开始打印G,结点G遍历完成。
10.新的第三步打印结点后,开始执行PreorderTraversal(BT->Left),由于BT->Left为空,开始执行PreorderTraversal(BT->Right),开始执行第四步调用,由于不为空,执行打印结点J,结点J遍历完成。
11.第四步执行完打印后,开始执行PreorderTraversal(BT->Left),由于BT->Left为空,立刻返回,开始执行PreorderTraversal(BT->Right),由于BT->Right为空,立刻返回,此时第四步执行完毕,返回至第三步,第三步已经调用了PreorderTraversal(BT->Right)打印了J,所以第三步执行完毕,返回至第二步,第二步已经调用了PreorderTraversal(BT->Right)打印了G,所以第二步执行完毕,返回至第一步,此时第一步已经调用了PreorderTraversal(BT->Right)打印了C,第一步调用结束,整个递归过程也随之结束,遍历完了所以结点。
遍历顺序为:A->B->D->H->E->I->C->F->G->J
感悟:
1.递归的实质就是不断调用自身,来实现某些功能,递归的结束标志就是第一次函数调用结束。
2.在明白原理后,思考理解就不要一直想象它的具体调用过程,只需要看在哪里执行遍历,在哪里调用自身,一直往下调用的结束条件是什么,如何才会完成第一步调用。
3.关于树的调用次数问题,可以直接看树的层数,可以这样理解,当前是第几层,就是第几次在调用,不过有着先左后右的顺序。
6.树的前序遍历的递归原理其实就是深度优先搜索的原理:一个结点有一条路就走一条路,等所有的路走完了,就返回至上一个结点。
此章结束。