二叉樹神級遍歷演算法:morris遍歷演算法
阿新 • • 發佈:2022-02-18
morris遍歷的實質
建立一種機制,對於沒有左子樹的節點只到達一次,對於有左子樹的節點會到達兩次
不積跬步,無以至千里;不積小流,無以成江海。morris遍歷的實現原則
記作當前節點為cur。
- 如果cur無左孩子,cur向右移動(cur=cur.right)
- 如果cur有左孩子,找到cur左子樹上最右的節點,記為mostright
- 如果mostright的right指標指向空,讓其指向cur,cur向左移動(cur=cur.left)
- 如果mostright的right指標指向cur,讓其指向空,cur向右移動(cur=cur.right)
實現以上的原則,即實現了morris遍歷。
morris遍歷的實質
建立一種機制,對於沒有左子樹的節點只到達一次,對於有左子樹的節點會到達兩次morris遍歷的例項
一個樹若按層遍歷的結構為{1,2,3,4,5,6,7},即該樹為滿二叉樹,頭結點值為1,左右孩子為2,3,葉節點為4,5,6,7一開始圖示:
我們按照morris遍歷來遍歷該樹。
1)首先cur來到頭結點1,按照morris原則的第二條第一點,它存在左孩子,cur左子樹上最右的節點為5,它的right指標指向空,所以讓其指向1,cur向左移動到2。
2)2有左孩子,且它左子樹最右的節點4指向空,按照morris原則的第二條第一點,讓4的right指標指向2,cur向左移動到4
3)4不存在左孩子,按照morris原則的第一條,cur向右移動,在第二步中,4的right指標已經指向了2,所以cur會回到2
4)重新回到2,有左孩子,它左子樹最右的節點為4,但是在第二步中,4的right指標已經指向了2,不為空。所以按照morris原則的第二條第二點,2向右移動到5,同時4的right指標重新指向空
5)5不存在左孩子,按照morris原則的第一條,cur向右移動,在第一步中,5的right指標已經指向了1,所以cur會回到1
6)cur回到1,回到頭結點,左子樹遍歷完成,1有左孩子,左子樹上最右的節點為5,它的right指標指向1,按照morris原則的第二條第二點,1向右移動到3,同時5的right指標重新指回空
……
當到達最後一個節點7時,按照流程下來,此時7無左右孩子,遍歷結束。
classSolution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<Integer>(); TreeNode predecessor = null; while (root != null) { if (root.left != null) { // predecessor 節點就是當前 root 節點向左走一步,然後一直向右走至無法走為止 predecessor = root.left; while (predecessor.right != null && predecessor.right != root) { predecessor = predecessor.right; } // 讓 predecessor 的右指標指向 root,繼續遍歷左子樹 if (predecessor.right == null) { predecessor.right = root; root = root.left; } // 說明左子樹已經訪問完了,我們需要斷開連結 else { res.add(root.val); predecessor.right = null; root = root.right; } } // 如果沒有左孩子,則直接訪問右孩子 else { res.add(root.val); root = root.right; } } return res; } }