自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一個(gè)套路,寫(xiě)出來(lái)二叉樹(shù)的迭代遍歷

開(kāi)發(fā) 前端
實(shí)踐過(guò)的同學(xué),也會(huì)發(fā)現(xiàn)使用迭代法實(shí)現(xiàn)先中后序遍歷,很難寫(xiě)出統(tǒng)一的代碼,不像是遞歸法,實(shí)現(xiàn)了其中的一種遍歷方式,其他兩種只要稍稍改一下節(jié)點(diǎn)順序就可以了。

[[411706]]

二叉樹(shù)的統(tǒng)一迭代法

此時(shí)我們?cè)诙鏄?shù):一入遞歸深似海,從此offer是路人中用遞歸的方式,實(shí)現(xiàn)了二叉樹(shù)前中后序的遍歷。

在二叉樹(shù):聽(tīng)說(shuō)遞歸能做的,棧也能做!中用棧實(shí)現(xiàn)了二叉樹(shù)前后中序的迭代遍歷(非遞歸)。

之后我們發(fā)現(xiàn)迭代法實(shí)現(xiàn)的先中后序,其實(shí)風(fēng)格也不是那么統(tǒng)一,除了先序和后序,有關(guān)聯(lián),中序完全就是另一個(gè)風(fēng)格了,一會(huì)用棧遍歷,一會(huì)又用指針來(lái)遍歷。

實(shí)踐過(guò)的同學(xué),也會(huì)發(fā)現(xiàn)使用迭代法實(shí)現(xiàn)先中后序遍歷,很難寫(xiě)出統(tǒng)一的代碼,不像是遞歸法,實(shí)現(xiàn)了其中的一種遍歷方式,其他兩種只要稍稍改一下節(jié)點(diǎn)順序就可以了。

其實(shí)針對(duì)三種遍歷方式,使用迭代法是可以寫(xiě)出統(tǒng)一風(fēng)格的代碼!

重頭戲來(lái)了,接下來(lái)介紹一下統(tǒng)一寫(xiě)法。

我們以中序遍歷為例,在二叉樹(shù):聽(tīng)說(shuō)遞歸能做的,棧也能做!中提到說(shuō)使用棧的話,無(wú)法同時(shí)解決訪問(wèn)節(jié)點(diǎn)(遍歷節(jié)點(diǎn))和處理節(jié)點(diǎn)(將元素放進(jìn)結(jié)果集)不一致的情況。

那我們就將訪問(wèn)的節(jié)點(diǎn)放入棧中,把要處理的節(jié)點(diǎn)也放入棧中但是要做標(biāo)記。

如何標(biāo)記呢,就是要處理的節(jié)點(diǎn)放入棧之后,緊接著放入一個(gè)空指針作為標(biāo)記。 這種方法也可以叫做標(biāo)記法。

迭代法中序遍歷

中序遍歷代碼如下:(詳細(xì)注釋)

  1. class Solution { 
  2. public
  3.     vector<int> inorderTraversal(TreeNode* root) { 
  4.         vector<int> result; 
  5.         stack<TreeNode*> st; 
  6.         if (root != NULL) st.push(root); 
  7.         while (!st.empty()) { 
  8.             TreeNode* node = st.top(); 
  9.             if (node != NULL) { 
  10.                 st.pop(); // 將該節(jié)點(diǎn)彈出,避免重復(fù)操作,下面再將右中左節(jié)點(diǎn)添加到棧中 
  11.                 if (node->right) st.push(node->right);  // 添加右節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧) 
  12.  
  13.                 st.push(node);                          // 添加中節(jié)點(diǎn) 
  14.                 st.push(NULL); // 中節(jié)點(diǎn)訪問(wèn)過(guò),但是還沒(méi)有處理,加入空節(jié)點(diǎn)做為標(biāo)記。 
  15.  
  16.                 if (node->left) st.push(node->left);    // 添加左節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧) 
  17.             } else { // 只有遇到空節(jié)點(diǎn)的時(shí)候,才將下一個(gè)節(jié)點(diǎn)放進(jìn)結(jié)果集 
  18.                 st.pop();           // 將空節(jié)點(diǎn)彈出 
  19.                 node = st.top();    // 重新取出棧中元素 
  20.                 st.pop(); 
  21.                 result.push_back(node->val); // 加入到結(jié)果集 
  22.             } 
  23.         } 
  24.         return result; 
  25.     } 
  26. }; 

看代碼有點(diǎn)抽象我們來(lái)看一下動(dòng)畫(huà)(中序遍歷):

中序遍歷迭代(統(tǒng)一寫(xiě)法)

動(dòng)畫(huà)中,result數(shù)組就是最終結(jié)果集。

可以看出我們將訪問(wèn)的節(jié)點(diǎn)直接加入到棧中,但如果是處理的節(jié)點(diǎn)則后面放入一個(gè)空節(jié)點(diǎn), 這樣只有空節(jié)點(diǎn)彈出的時(shí)候,才將下一個(gè)節(jié)點(diǎn)放進(jìn)結(jié)果集。

此時(shí)我們?cè)賮?lái)看前序遍歷代碼。

迭代法前序遍歷

迭代法前序遍歷代碼如下:(注意此時(shí)我們和中序遍歷相比僅僅改變了兩行代碼的順序)

  1. class Solution { 
  2. public
  3.     vector<int> preorderTraversal(TreeNode* root) { 
  4.         vector<int> result; 
  5.         stack<TreeNode*> st; 
  6.         if (root != NULL) st.push(root); 
  7.         while (!st.empty()) { 
  8.             TreeNode* node = st.top(); 
  9.             if (node != NULL) { 
  10.                 st.pop(); 
  11.                 if (node->right) st.push(node->right);  // 右 
  12.                 if (node->left) st.push(node->left);    // 左 
  13.                 st.push(node);                          // 中 
  14.                 st.push(NULL); 
  15.             } else { 
  16.                 st.pop(); 
  17.                 node = st.top(); 
  18.                 st.pop(); 
  19.                 result.push_back(node->val); 
  20.             } 
  21.         } 
  22.         return result; 
  23.     } 
  24. }; 

迭代法后序遍歷

后續(xù)遍歷代碼如下:(注意此時(shí)我們和中序遍歷相比僅僅改變了兩行代碼的順序)

  1. class Solution { 
  2. public
  3.     vector<int> postorderTraversal(TreeNode* root) { 
  4.         vector<int> result; 
  5.         stack<TreeNode*> st; 
  6.         if (root != NULL) st.push(root); 
  7.         while (!st.empty()) { 
  8.             TreeNode* node = st.top(); 
  9.             if (node != NULL) { 
  10.                 st.pop(); 
  11.                 st.push(node);                          // 中 
  12.                 st.push(NULL); 
  13.  
  14.                 if (node->right) st.push(node->right);  // 右 
  15.                 if (node->left) st.push(node->left);    // 左 
  16.  
  17.             } else { 
  18.                 st.pop(); 
  19.                 node = st.top(); 
  20.                 st.pop(); 
  21.                 result.push_back(node->val); 
  22.             } 
  23.         } 
  24.         return result; 
  25.     } 
  26. }; 

總結(jié)

此時(shí)我們寫(xiě)出了統(tǒng)一風(fēng)格的迭代法,不用在糾結(jié)于前序?qū)懗鰜?lái)了,中序?qū)懖怀鰜?lái)的情況了。

但是統(tǒng)一風(fēng)格的迭代法并不好理解,而且想在面試直接寫(xiě)出來(lái)還有難度的。

所以大家根據(jù)自己的個(gè)人喜好,對(duì)于二叉樹(shù)的前中后序遍歷,選擇一種自己容易理解的遞歸和迭代法。

其他語(yǔ)言版本

Java:迭代法前序遍歷代碼如下:

  1. class Solution { 
  2.     public List<Integer> preorderTraversal(TreeNode root) { 
  3.         List<Integer> result = new LinkedList<>(); 
  4.         Stack<TreeNode> st = new Stack<>(); 
  5.         if (root != null) st.push(root); 
  6.         while (!st.empty()) { 
  7.             TreeNode node = st.peek(); 
  8.             if (node != null) { 
  9.                 st.pop(); // 將該節(jié)點(diǎn)彈出,避免重復(fù)操作,下面再將右中左節(jié)點(diǎn)添加到棧中 
  10.                 if (node.right!=null) st.push(node.right);  // 添加右節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧) 
  11.                 if (node.left!=null) st.push(node.left);    // 添加左節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧) 
  12.                 st.push(node);                          // 添加中節(jié)點(diǎn) 
  13.                 st.push(null); // 中節(jié)點(diǎn)訪問(wèn)過(guò),但是還沒(méi)有處理,加入空節(jié)點(diǎn)做為標(biāo)記。 
  14.                  
  15.             } else { // 只有遇到空節(jié)點(diǎn)的時(shí)候,才將下一個(gè)節(jié)點(diǎn)放進(jìn)結(jié)果集 
  16.                 st.pop();           // 將空節(jié)點(diǎn)彈出 
  17.                 node = st.peek();    // 重新取出棧中元素 
  18.                 st.pop(); 
  19.                 result.add(node.val); // 加入到結(jié)果集 
  20.             } 
  21.         } 
  22.         return result; 
  23.     } 

迭代法中序遍歷代碼如下:

  1. class Solution { 
  2. public List<Integer> inorderTraversal(TreeNode root) { 
  3.         List<Integer> result = new LinkedList<>(); 
  4.     Stack<TreeNode> st = new Stack<>(); 
  5.     if (root != null) st.push(root); 
  6.     while (!st.empty()) { 
  7.         TreeNode node = st.peek(); 
  8.         if (node != null) { 
  9.             st.pop(); // 將該節(jié)點(diǎn)彈出,避免重復(fù)操作,下面再將右中左節(jié)點(diǎn)添加到棧中 
  10.             if (node.right!=null) st.push(node.right);  // 添加右節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧) 
  11.             st.push(node);                          // 添加中節(jié)點(diǎn) 
  12.             st.push(null); // 中節(jié)點(diǎn)訪問(wèn)過(guò),但是還沒(méi)有處理,加入空節(jié)點(diǎn)做為標(biāo)記。 
  13.  
  14.             if (node.left!=null) st.push(node.left);    // 添加左節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧) 
  15.         } else { // 只有遇到空節(jié)點(diǎn)的時(shí)候,才將下一個(gè)節(jié)點(diǎn)放進(jìn)結(jié)果集 
  16.             st.pop();           // 將空節(jié)點(diǎn)彈出 
  17.             node = st.peek();    // 重新取出棧中元素 
  18.             st.pop(); 
  19.             result.add(node.val); // 加入到結(jié)果集 
  20.         } 
  21.     } 
  22.     return result; 

迭代法后序遍歷代碼如下:

  1. class Solution { 
  2.    public List<Integer> postorderTraversal(TreeNode root) { 
  3.         List<Integer> result = new LinkedList<>(); 
  4.         Stack<TreeNode> st = new Stack<>(); 
  5.         if (root != null) st.push(root); 
  6.         while (!st.empty()) { 
  7.             TreeNode node = st.peek(); 
  8.             if (node != null) { 
  9.                 st.pop(); // 將該節(jié)點(diǎn)彈出,避免重復(fù)操作,下面再將右中左節(jié)點(diǎn)添加到棧中 
  10.                 st.push(node);                          // 添加中節(jié)點(diǎn) 
  11.                 st.push(null); // 中節(jié)點(diǎn)訪問(wèn)過(guò),但是還沒(méi)有處理,加入空節(jié)點(diǎn)做為標(biāo)記。 
  12.                 if (node.right!=null) st.push(node.right);  // 添加右節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧) 
  13.                 if (node.left!=null) st.push(node.left);    // 添加左節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧)          
  14.                                 
  15.             } else { // 只有遇到空節(jié)點(diǎn)的時(shí)候,才將下一個(gè)節(jié)點(diǎn)放進(jìn)結(jié)果集 
  16.                 st.pop();           // 將空節(jié)點(diǎn)彈出 
  17.                 node = st.peek();    // 重新取出棧中元素 
  18.                 st.pop(); 
  19.                 result.add(node.val); // 加入到結(jié)果集 
  20.             } 
  21.         } 
  22.         return result; 
  23.    } 

Python:

迭代法前序遍歷:

  1. class Solution: 
  2.     def preorderTraversal(self, root: TreeNode) -> List[int]: 
  3.         result = [] 
  4.         st= [] 
  5.         if root: 
  6.             st.append(root) 
  7.         while st: 
  8.             node = st.pop() 
  9.             if node != None: 
  10.                 if node.right: #右 
  11.                     st.append(node.right
  12.                 if node.left: #左 
  13.                     st.append(node.left
  14.                 st.append(node) #中 
  15.                 st.append(None) 
  16.             else
  17.                 node = st.pop() 
  18.                 result.append(node.val) 
  19.         return result 

迭代法中序遍歷:

  1. class Solution: 
  2.     def inorderTraversal(self, root: TreeNode) -> List[int]: 
  3.         result = [] 
  4.         st = [] 
  5.         if root: 
  6.             st.append(root) 
  7.         while st: 
  8.             node = st.pop() 
  9.             if node != None: 
  10.                 if node.right: #添加右節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧) 
  11.                     st.append(node.right
  12.                  
  13.                 st.append(node) #添加中節(jié)點(diǎn) 
  14.                 st.append(None) #中節(jié)點(diǎn)訪問(wèn)過(guò),但是還沒(méi)有處理,加入空節(jié)點(diǎn)做為標(biāo)記。 
  15.                  
  16.                 if node.left: #添加左節(jié)點(diǎn)(空節(jié)點(diǎn)不入棧) 
  17.                     st.append(node.left
  18.             else: #只有遇到空節(jié)點(diǎn)的時(shí)候,才將下一個(gè)節(jié)點(diǎn)放進(jìn)結(jié)果集 
  19.                 node = st.pop() #重新取出棧中元素 
  20.                 result.append(node.val) #加入到結(jié)果集 
  21.         return result 

迭代法后序遍歷:

  1. class Solution: 
  2.     def postorderTraversal(self, root: TreeNode) -> List[int]: 
  3.         result = [] 
  4.         st = [] 
  5.         if root: 
  6.             st.append(root) 
  7.         while st: 
  8.             node = st.pop() 
  9.             if node != None: 
  10.                 st.append(node) #中 
  11.                 st.append(None) 
  12.                  
  13.                 if node.right: #右 
  14.                     st.append(node.right
  15.                 if node.left: #左 
  16.                     st.append(node.left
  17.             else
  18.                 node = st.pop() 
  19.                 result.append(node.val) 
  20.         return result 

舊文鏈接:二叉樹(shù):前中后序迭代方式的寫(xiě)法就不能統(tǒng)一一下么?

 

責(zé)任編輯:武曉燕 來(lái)源: 代碼隨想錄
相關(guān)推薦

2020-04-27 07:05:58

二叉樹(shù)左子樹(shù)右子樹(shù)

2021-07-13 11:32:41

二叉樹(shù)數(shù)據(jù)結(jié)構(gòu)算法

2013-07-15 16:35:55

二叉樹(shù)迭代器

2022-10-26 23:58:02

二叉樹(shù)數(shù)組算法

2021-04-20 08:37:14

數(shù)據(jù)結(jié)構(gòu)二叉樹(shù)樹(shù)

2023-05-08 15:57:16

二叉樹(shù)數(shù)據(jù)結(jié)構(gòu)

2021-09-15 07:56:32

二叉樹(shù)層次遍歷

2021-02-28 22:00:28

二叉樹(shù)節(jié)點(diǎn)序列

2021-09-13 17:58:11

二叉樹(shù)層序算法

2009-08-11 13:29:57

C#二叉樹(shù)遍歷

2021-01-13 10:03:36

二叉樹(shù)層序遍歷層次遍歷

2021-05-06 17:46:30

二叉樹(shù)數(shù)據(jù)結(jié)構(gòu)

2021-04-19 07:47:42

數(shù)據(jù)結(jié)構(gòu)二叉樹(shù)Tree

2024-01-23 12:54:00

C++編程語(yǔ)言代碼

2021-04-28 20:12:27

數(shù)據(jù)結(jié)構(gòu)創(chuàng)建

2021-08-27 11:36:44

二叉樹(shù)回溯節(jié)點(diǎn)

2021-09-29 10:19:00

算法平衡二叉樹(shù)

2021-12-17 14:26:58

二叉樹(shù)節(jié)點(diǎn)數(shù)量

2021-03-17 08:19:22

二叉樹(shù)LeetCode樹(shù)

2021-11-29 10:40:58

二叉樹(shù)鏡像節(jié)點(diǎn)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)