1. 程式人生 > >演算法--20181109--二叉樹中序遍歷非遞迴實現

演算法--20181109--二叉樹中序遍歷非遞迴實現

1.二叉樹的中序遍歷

首先看一下遞迴方式的實現方式:

class TreeNode:
    left = None
    right = None
    var = 0
    def __init__(self, var):
        self.var = var
        
def inOrder(root):
    if root == None: 
        return
    inOrder(root.left)
    print (root.var)
    inOrder(root.right)

如果傳入節點為空則直接返回,否則遞迴呼叫inOrder(root.left)即不斷搜尋二叉樹最左邊節點,當找到最左邊節點時,root.left==null呼叫inorder直接返回,繼續執行print函式,輸出之後繼續執行inOrder(root.right) 即當輸出某個節點時,指標應該指向輸出節點的右節點

def inOrder2(root):
    if root == None:
        return
    #指標
    p = root
    #棧
    s = []
    while p!=None or len(s)>0:
        #將二叉樹的從根到最左節點路徑上節點不斷入棧
        if(p!=None):
            s.append(p)
            p = p.left
        else:
            #從棧中彈出
            p = s.pop()
            print (p.var)
            #當列印完畢只有  指標指向列印節點的右節點
            p = p.right

2.二叉樹的先序遍歷:

遞迴方式實現先序遍歷:

def preOrder(root):
    if root == None:
        return
    print(root.var)
    preOrder(root.left)
    preOrder(root.right)

當傳入節點非空時,立刻列印該節點,然後依次遞迴遍歷left  right節點 先訪問根 然後一直訪問根的左節點,直到某個節點左節點為空,此時訪問該節點的右節點

非遞迴實現方式:

def preOrder2(root):
    if root == None:
        return
    p = root
    s = []
    s.append(p)
    while len(s)>0:
        p = s.pop()
        print(p.var)
        if p.right != None:
            s.append(p.right)
        if p.left != None:
            s.append(p.left)

首先將根節點入棧,然後彈出輸出節點值,依次判斷右 左節點是否為空,當節點非空時,依次入棧,則出棧順序對應左右,即實現了先序遍歷。

3.二叉樹的後序遍歷:

使用一個指標來遍歷樹節點   使用一個指標來記錄上一個被訪問的節點   當訪問某個節點時,首先入棧,若該節點左右孩子均為空可以直接訪問,若左右孩子其一為空並且上一個訪問的節點是其左右孩子則該節點也可以訪問,若該節點左右孩子非空,則依次將右左節點入棧。

遞迴方式實現後序遍歷:

def postOrder(root):
    if root == None:
        return
    postOrder(root.left)
    postOrder(root.right)
    print (root.var)

如果root為空,直接返回  遞迴呼叫root.left以及root.right 等到root.left==root.right==null時或者上一個被訪問的節點是樹的左右節點之一,本節點才會輸出。

非遞迴實現方式:

根元素入棧,取出棧頂元素  若該元素左右節點為空 或者上一個被訪問的節點非空並且上一個被訪問的節點是棧頂元素的左右節點之一,則彈出棧頂元素,輸出該元素 標記last=p   否則,說明該節點不能輸出則將其右左節點依次入棧。

def postOrder2(root):
    if root == None:
        return
    s = []
    p = root
    s.append(p)
    last = None
    while len(s)>0:
        p = s[len(s)-1]
        if(p.left==None and p.right==None) or (last!=None and p.left==last or p.right==last):
            p = s.pop()
            print (p.var)
            last = p
        else:
            if p.right!=None:
                s.append(p.right)
            if p.left!=None:
                s.append(p.left)

4.二叉樹的層序遍歷:

利用一個佇列,根節點入隊  迴圈遍歷 佇列中元素依次出隊輸出  然後 隊的左右節點依次入隊

def levelOrder(root):
    if root==None:
        return
    q = []
    p = root
    q.append(p)
    while len(q)>0:
        p = q.pop(0)
        print (p.var)
        if p.left!=None:
            q.append(p.left)
        if p.right!=None:
            q.append(p.right)

5.分行列印二叉樹

利用一個佇列  首先根元素入隊  然後迴圈 每一次迴圈開始佇列中儲存上一層元素,首選計算本一層元素總數量size  然後遍歷上一層所有元素將元素放置於一個list中,如果該元素左右節點非空,則全部入隊,這樣一個迴圈結束,下一層的元素已經全部入隊,準備下一次迴圈的開始

def levelOrder2(root):
    if root==None:
        return
    q = []
    p = root
    q.append(p)
    while len(q)>0:
        size = len(q)
        num = []
        while size>0:          
            p = q.pop(0)
            num.append(p.var)
            if p.left!=None:
                q.append(p.left)
            if p.right!=None:
                q.append(p.right)
            size = size - 1
        print (num)

6.按奇偶行列印二叉樹  奇行從左到右   偶行從右到左

將每一行的結果記錄到list中然後按照奇偶行決定是否翻轉陣列

def levelOrder3(root):
    if root==None:
        return
    q = []
    p = root
    q.append(p)
    line = 1
    while len(q)>0:
        size = len(q)
        num = []
        while size>0:          
            p = q.pop(0)
            num.append(p.var)
            if p.left!=None:
                q.append(p.left)
            if p.right!=None:
                q.append(p.right)
            size = size - 1
        if line%2==1:
            print (num)         
        else:
            num.reverse()
            print (num)
        line = line + 1

python中List使用: