二叉查找樹全面詳細介紹

一、前言

重新梳理整理歸納二叉搜索樹。主要參考《C++數據結構與算法》。

 

二、定義

二叉排序樹(Binary Sort Tree),又稱二叉查找樹(Binary Search Tree),亦稱二叉搜索樹。是數據結構中的一類。在一般情況下,查詢效率比鏈表結構要高。

二叉排序樹定義,一棵空樹,或者是具有下列性質的二叉樹

  1. 若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
  2. 若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
  3. 左、右子樹也分別爲二叉排序樹;
  4. 沒有鍵值相等的結點。

 

三、二叉搜索樹接口操作說明

二叉搜索樹的基本操作有:搜索(查找)、遍歷、插入、刪除

3.1 搜索

在樹中定位一個元素的算法相當直觀,《4.2 搜索(查找)》實現了該算法。對於每個節點,算法將要定位的值與當前所指節點中存儲的值進行比較。如果該值小於存儲值,則轉向左子樹;如果該值大於存儲的值,則轉向右子樹。如果二者相同,很明顯查找過程可以結束了。如果沒有其他可以查找的節點,該查找過程也終止,這表示該值不在該樹中。

搜索實現方法可以分爲:遞歸搜索、非遞歸搜索《4.2 搜索(查找)》實現了該算法。

 

3.2 遍歷

樹的遍歷是當且僅當訪問樹中每個節點一次的過程。遍歷可以解釋爲把所有的節點放在一條線上,或者將樹線性化。

遍歷的定義只指定了個條件:每個節點儀訪問一次,沒有指定這些節點的訪問順序。因此,節點有多少種排列方式,就有多少種遍歷方法。對於有n個節點的樹,共有n!個不同的遍歷方式。然而,大多數遍歷方式是混亂的,很難從中找到規律,因此實現這樣的遍歷缺乏普遍性。對於每個n,必須實現一套獨立的遍歷程序,其中只有很少的幾個可以用於不同數量的數據。在如此多的遍歷方法中,大多數方法明顯沒有什麼用處,這裏僅介紹兩類方法,即深度優先遍歷廣度優先遍歷

遍歷可以分爲:深度優先遍歷(DFS)廣度優先遍歷(BFS)

3.2.1 深度優先遍歷(DFS)

深度優先遍歷將盡可能地向左(或向右)進行,在遇到第一個轉折點時,向左(或向右)一步,然後,再儘可能地向左(或向右)發展。這一過程,一直重複,直至訪問了所有的節點爲止。然而,這一定義並沒有清楚地指明什麼時候訪問節點:在沿着樹向下進行之前還是在折返之後?深度優先遍歷有許多變種。

這種類型的遍歷中,有3個有趣的任務:

  • v——訪問節點
  • L——遍歷左子樹
  • R——遍歷右子樹

如果這些任務在每個節點上都以相同的順序執行,就形成了有序遍歷。這3種任務自身共有3!=6種排序方式,因此,總共有6種有序深度優先遍歷:VLR,LVR,LRV,VRL,RVL,RLV。

遍歷方式看起來還是有些多,如果規定訪問總是從左向右移動,則上面的遍歷方式可以縮減爲3種。這三種遍歷方式的標準名稱爲:

  • VLR——前序樹遍歷
  • LVR——中字樹遍歷
  • LVR——後序樹遍

深度優先遍歷(DFS)按照遍歷順序可以分爲:前序遍歷、中序遍歷、後序遍歷

深度優先遍歷(DFS)按照實現方法可以分爲:遞歸遍歷實現、非遞歸遍歷實現、Morris遍歷實現

深度優先遍歷接口有9(3*3)個。

備註:遞歸遍歷實現、非遞歸遍歷實現、Morris遍歷實:詳細講解:https://blog.csdn.net/nie2314550441/article/details/107073598

 

3.2.2 廣度優先遍歷(BFS)

隊列實現。《4.5 插入》實現了插入節點算法的代碼。

廣度優先遍歷從最低層(或者最高層)開始,向下(或向上)逐層訪問每個節點,在每一層次上,從左到右(或從右到左)訪問每個節點。這樣就有4種訪問方式,其中的種訪問方式(從上到下、從左到右的廣度優先遍歷方式)。

當使用隊列時,這種遍歷方式的實現相當直接。假設從上到下、從左到右進行廣度優先遍歷。在訪問了一個節點後,它的子節點(如果有的話)就放到隊列的末尾,然後訪問隊列頭部的節點。對於層次爲n的節點,它的子節點位於第n+1層,如果將該節點的所有子節點都放到隊列的末尾,那麼,這些節點將在第n層的所有節點都訪問後再訪問。這樣,算法就滿足了“第n層的所有節點都必須在第n+1層的節點之前訪問”的條件。實現過程見——4.4 廣度優先遍歷。

 

3.3 插入

要插入鍵值爲el的新節點,必須找到樹中的一個終端節點,並將新節點與該節點連接。要找到這樣一個終端節點,可以使用與查找樹相同的技術:在掃描樹的過程中,比較鍵值el與當前檢查的節點的鍵值。如果el小於該鍵值,就測試當前節點的左子節點,否則,就測試當前節點的右子節點。如果要測試的p的子節點爲空,就停止掃描,新節點將成爲p的子節點。圖6-12顯示了這一過程。

插入實現方法可以分爲:非遞歸實現、遞歸實現

 

3.4 刪除

刪除節點有兩種方案:查找合併刪除、查找複製刪除

執行刪除操作的複雜度取決於要刪除的節點在樹中的位置。刪除有兩個子樹的節點比刪除葉節點困難得多,刪除算法的複雜度與被刪除節點的子節點數目成正比。從二叉查找樹中刪除節點有三種情況:

(1)要刪除的節點是一個葉節點,該節點沒有子節點。這種情況最容易處理。其父節點的相應指針設置爲空,該節點通過delete操作被刪除,如圖6-14所示。

(2)要刪除的節點有一個子節點,這種情況也不復雜。父節點中指向該節點的指針重新設置爲指向被刪除節點的子節點。這樣,被刪除節點的子節點提升一個層次,其後的所有後裔節點根據家族關係依次提升一個層次。例如,要刪除圖6-15中包含20的節點,可以將其父節點15的右指針指向其唯的子節點16。

(3)要刪除的節點有兩個子節點。在這種情況中,無法一步完成刪除操作,因爲父節點的右指針或左指針不能同時指向被刪除節點的兩個子節點。本節討論解決這一問題的兩種不同方案。

3.4.1 查找合併刪除

查找合併刪除:查找到刪除節點P,將P節點刪除,然後將左節點L、右節點R進行合併,最後將P父節點(如果有的話)指向L節點。

1)需要刪除的節點,有左右孩子節點,下圖中刪除節點是點P,灰色節點表示該節點可以有可以沒有。P節點可以有父節點,可以沒有,如果有父節點,可以是父節點的左節點也可以是右節點,對結果沒有影響。

2)P節點刪除之後剩下:P節點父節點(如果有的話)、左節點L、右節點R。查找合併刪除:查找到P節,將P節點刪除,然後將P節點父節點(如果有的話)、左節點L、右節點R進行合併,準確來說是將左節點L、右節點R進行合併。

3)找到P節點右節點中最大節點,並將R節點接在最大節點右節點上,P父節點(如果有的話)指向L節點。

P節點的右節點中最大節點查找方法,一直查找L節點的右節點,直到最後一個沒有右節點的節點D即爲P節點中最大的節點,D節點的右節點指向R節點,合併完成,例如下圖:

3.4.2 查找複製刪除

查找複製刪除:查找一個可以替換P節點位置的節點,將該節點元素複製到P節點中,並將該節點刪除。能替換P節點位置的節點有兩個,一個是P節點左節點中元素最大的節點,另一個是P節點右節點中元素最小的節點,這裏用到的是P節點左節點中元素最大的節點。

1)需要刪除的節點,有左右孩子節點,下圖中刪除節點是點P,灰色節點表示該節點可以有可以沒有。P節點可以有父節點,可以沒有,如果有父節點,可以是父節點的左節點也可以是右節點,對結果沒有影響。

2)查找P節點左節點中最大的節點D

3) 將D節點元素複製到P節點中,D節點的父節點Pre指向D節點左節點,刪除D節點。需要說明一下,如果Pre和P是同一個節點,則Pre左節點指向T節點,如果Pre和P不是同一個節點,則Pre右節點指向T節點。

 

四、二叉搜索樹接口C++實現(代碼說明)

4.1 基本定義

爲了方便使用對棧和隊列一些接口進行了重寫。

template<class T>
class Stack: public stack<T> 
{
public:
    T pop() 
    {
        T tmp = stack<T>::top();
        stack<T>::pop();
        return tmp;
    }
};

template<class T>
class Queue: public queue<T> 
{
public:
    T dequeue() 
    {
        T tmp = queue<T>::front();
        queue<T>::pop();
        return tmp;
    }

    void enqueue(const T& m_el) 
    {
        queue<T>::push(m_el);
    }
};

template<class T>
class BSTNode 
{
public:
    BSTNode()
    {
        m_el = 0;
        m_left = nullptr;
        m_right = nullptr;
    }

    BSTNode(const T& e, BSTNode<T>* l = nullptr, BSTNode<T> * r = nullptr)
    {
        m_el = e; 
        m_left = l; 
        m_right = r;
    }

    T m_el;
    BSTNode<T>* m_left;
    BSTNode<T>* m_right;
};

 

4.2 搜索(查找)

遞歸實現和非遞歸實現,很容易理解直接看代碼即可。

// 搜索,遞歸實現
template<class T>
T* BST<T>::recursiveSearch(BSTNode<T>* p, const T& m_el) const 
{
    if (p != 0)
    {
        if (m_el == p->m_el)
            return &p->m_el;
        else if (m_el < p->m_el)
            return recursiveSearch(p->m_left, m_el);
        else 
            return recursiveSearch(p->m_right, m_el);
    }
    else
        return 0;
}

// 搜索,非遞歸實現
template<class T>
T* BST<T>::search(BSTNode<T>* p, const T& m_el) const 
{
    while (p != 0)
    {
        if (m_el == p->m_el)
            return &p->m_el;
        else if (m_el < p->m_el)
            p = p->m_left;
        else 
            p = p->m_right;
    }

    return 0;
}

 

4.3 深度優先遍歷

4.3.1 遞歸實現:前序遍歷、中序遍歷、後序遍歷

遞歸實現的,前序遍歷、中序遍歷、後序遍歷直接看代碼即可。

// 前序遍歷,遞歸實現
template<class T>
void BST<T>::preorder(BSTNode<T>* p)
{
	if (p != 0)
	{
        visit(p);
        preorder(p->m_left);
        preorder(p->m_right);
	}
}

// 中序遍歷,遞歸實現
template<class T>
void BST<T>::inorder(BSTNode<T>* p) 
{
    if (p != 0) 
    {
        inorder(p->m_left);
        visit(p);
        inorder(p->m_right);
    }
}

// 後序遍歷,遞歸實現
template<class T>
void BST<T>::postorder(BSTNode<T>* p) 
{
    if (p != 0) 
    {
        postorder(p->m_left);
        postorder(p->m_right);
        visit(p);
    }
}

4.3.2 非遞歸實現:前序遍歷、中序遍歷、後序遍歷

// 前序遍歷,非遞歸棧實現
template<class T>
void BST<T>::iterativePreorder() 
{
    Stack<BSTNode<T>*> travStack;
    BSTNode<T>* p = root;
    if (p != 0) 
    {
        travStack.push(p);
        while (!travStack.empty())
        {
            p = travStack.pop();
            visit(p);
            if (p->m_right != 0)
                travStack.push(p->m_right);

            if (p->m_left != 0)            
                travStack.push(p->m_left); 
        }
    }
}

// 中序遍歷,非遞歸棧實現
template<class T>
void BST<T>::iterativeInorder() 
{
    Stack<BSTNode<T>*> travStack;
    BSTNode<T>* p = root;
    while (p != nullptr) 
    {
        while (p != nullptr)
        {                 
            if (p->m_right)                
                travStack.push(p->m_right); 

            travStack.push(p);
            p = p->m_left;
        }

        p = travStack.pop();             
        while (!travStack.empty() && p->m_right == nullptr)
        { 
            visit(p);                                
            p = travStack.pop();
        }

        visit(p);                       
        if (!travStack.empty())          
            p = travStack.pop();
        else 
            p = nullptr;
    }
}

// 後序遍歷,非遞歸棧實現
template<class T>
void BST<T>::iterativePostorder() 
{
    Stack<BSTNode<T>*> travStack;
    BSTNode<T>* p = root, * q = root;
    while (p != nullptr) 
    {
        for (; p->m_left != nullptr; p = p->m_left)
            travStack.push(p);

        while (p->m_right == nullptr || p->m_right == q)
        {
            visit(p);
            q = p;
            if (travStack.empty())
                return;

            p = travStack.pop();
        }
        travStack.push(p);
        p = p->m_right;
    }
}

4.3.3 Morris遍歷:前序遍歷、中序遍歷、後序遍歷

// 前序遍歷,非遞歸Morris遍歷算法實現
template<class T>
void BST<T>::MorrisPreorder() 
{
    BSTNode<T>* p = root, * tmp;
    while (p != nullptr) 
    {
        if (p->m_left == nullptr)
        {
            visit(p);
            p = p->m_right;
        }
        else 
        {
            tmp = p->m_left;
            while (tmp->m_right != nullptr && tmp->m_right != p)
                tmp = tmp->m_right;   

            if (tmp->m_right == nullptr)
            {  
                visit(p);         
                tmp->m_right = p;    
                p = p->m_left;        
            }
            else 
            {                   
                tmp->m_right = nullptr;    
                p = p->m_right;       
            }                        
        }
    }
}

// 中序遍歷,非遞歸Morris遍歷算法實現
template<class T>
void BST<T>::MorrisInorder() 
{
    BSTNode<T>* p = root, * tmp;
    while (p != 0)
    {
        if (p->m_left == 0) 
        {
            visit(p);
            p = p->m_right;
        }
        else 
        {
            tmp = p->m_left;
            while (tmp->m_right != 0 &&
                tmp->m_right != p)  
                tmp = tmp->m_right;   
            if (tmp->m_right == 0) 
            {   
                tmp->m_right = p;    
                p = p->m_left;       
            }
            else 
            {                   
                visit(p);      
                tmp->m_right = 0;    
                p = p->m_right;      
            }                      
        }
    }
}

// 後序遍歷,非遞歸Morris遍歷算法實現
template<class T>
void BST<T>::MorrisPostorder() 
{
    BSTNode<T>* p = new BSTNode<T>(), * tmp, * q, * r, * s;
    p->m_left = root;
    while (p != 0)
    {
        if (p->m_left == 0)
            p = p->m_right;
        else
        {
            tmp = p->m_left;
            while (tmp->m_right != 0 && tmp->m_right != p)  
                tmp = tmp->m_right;   

            if (tmp->m_right == 0) 
            {   
                tmp->m_right = p;     
                p = p->m_left;        
            }
            else
            {             
                for (q = p->m_left, r = q->m_right, s = r->m_right;
                    r != p; q = r, r = s, s = s->m_right)
                    r->m_right = q;

                for (s = q->m_right; q != p->m_left;
                    q->m_right = r, r = q, q = s, s = s->m_right)
                    visit(q);

                visit(p->m_left);    
                tmp->m_right = 0;     
                p = p->m_right;      
            }                   
        }
    }
}

 

4.4 廣度優先遍歷

// 廣度優先遍歷:從上到下,從左到右
template<class T>
void BST<T>::breadthFirst() 
{
    Queue<BSTNode<T>*> queue;
    BSTNode<T>* p = root;
    if (p != 0) 
    {
        queue.enqueue(p);
        while (!queue.empty()) 
        {
            p = queue.dequeue();
            visit(p);
            if (p->m_left != 0)
                queue.enqueue(p->m_left);
            if (p->m_right != 0)
                queue.enqueue(p->m_right);
        }
    }
}

 

4.5 插入

非遞歸實現和遞歸實現

// 插入插入一個元素,非遞歸實現
template<class T>
bool BST<T>::insert(const T& m_el) 
{
    BSTNode<T>* p = root, * prev = 0;
    while (p != 0) 
    {  
        prev = p;
        if (m_el < p->m_el)
            p = p->m_left;
        else if (m_el > p->m_el)
            p = p->m_right;
        else
        {
            cout << "BST<T>::insert 插入相同的數據,插入失敗" << endl;
            return false;
        }
    }

    if (root == 0)    
        root = new BSTNode<T>(m_el);
    else if (m_el < prev->m_el)
        prev->m_left = new BSTNode<T>(m_el);
    else 
        prev->m_right = new BSTNode<T>(m_el);

	return true;
}

// 插入插入一個元素,遞歸實現
template<class T>
bool BST<T>::recursiveInsert(BSTNode<T>*& p, const T& m_el) 
{
    if (p == 0)
        p = new BSTNode<T>(m_el);
    else if (m_el < p->m_el)
        recursiveInsert(p->m_left, m_el);
    else if (m_el > p->m_el)
        recursiveInsert(p->m_right, m_el);
    else
    {
        cout << "BST<T>::recursiveInsert 插入相同的數據,插入失敗" << endl;
        return false;
    }
    
    return true; 
}

 

4.6 刪除

查找複製刪除和查找歸併刪除

// 查找複製刪除
template<class T>
void BST<T>::findAndDeleteByCopying(const T& m_el) 
{
    BSTNode<T>* p = root, * prev = 0;
    while (p != 0 && p->m_el != m_el) 
    {
        prev = p;
        if (m_el < p->m_el)
            p = p->m_left;
        else 
            p = p->m_right;
    }

    if (p != 0 && p->m_el == m_el)
    {
        if (p == root)
            deleteByCopying(root);
        else if (prev->m_left == p)
            deleteByCopying(prev->m_left);
        else
            deleteByCopying(prev->m_right);
	}
    else if (root != 0)
        cout << "m_el " << m_el << " is not in the tree\n";
    else 
        cout << "the tree is empty\n";
}

// 查找複製刪除
template<class T>
void BST<T>::deleteByCopying(BSTNode<T>*& node) 
{
    if (node == nullptr)
        return;
	
    BSTNode<T>* previous, * tmp = node;
    if (node->m_right == nullptr)                  // node 沒有右節點
        node = node->m_left;
    else if (node->m_left == nullptr)              // node 沒有左節點
        node = node->m_right;
    else 
    {
        tmp = node->m_left;							// node 有左、右節點
        previous = node;                   
        while (tmp->m_right != nullptr)
        {         
            previous = tmp;
            tmp = tmp->m_right;
        }

        node->m_el = tmp->m_el;                
        if (previous == node)
            previous->m_left = tmp->m_left;
        else 
            previous->m_right = tmp->m_left;   
    }

    delete tmp;                            
}

// 查找合併刪除
template<class T>
void BST<T>::findAndDeleteByMerging(const T& m_el) 
{
    BSTNode<T>* p = root, * prev = 0;
    while (p != 0 && p->m_el != m_el)
    {
        prev = p;
        if (m_el < p->m_el)
            p = p->m_left;
        else 
            p = p->m_right;
    }

	if (p != 0 && p->m_el == m_el)
	{
        if (p == root)
            deleteByMerging(root);
        else if (prev->m_left == p)
            deleteByMerging(prev->m_left);
        else
            deleteByMerging(prev->m_right);
	}
    else if (root != 0)
        cout << "m_el " << m_el << " is not in the tree\n";
    else cout << "the tree is empty\n";
}

// 查找合併刪除
template<class T>
void BST<T>::deleteByMerging(BSTNode<T>*& node) 
{
    if (node == nullptr)
        return;

    BSTNode<T>* tmp = node;
    if (node->m_right == nullptr)           // node 沒有右節點
        node = node->m_left;     
    else if (node->m_left == nullptr)       // node 沒有左節點
        node = node->m_right;    
    else 
    {                      
        tmp = node->m_left;      
        while (tmp->m_right != nullptr)
            tmp = tmp->m_right;

        tmp->m_right = node->m_right;           															
        tmp = node;							
        node = node->m_left;					
    }

    delete tmp;								
}

 

五、完整代碼

// 通用二叉查找樹的實現
#pragma once
#include <queue>
#include <stack>
#include <iostream>
using namespace std;

template<class T>
class Stack: public stack<T> 
{
public:
    T pop() 
    {
        T tmp = stack<T>::top();
        stack<T>::pop();
        return tmp;
    }
};

template<class T>
class Queue: public queue<T> 
{
public:
    T dequeue() 
    {
        T tmp = queue<T>::front();
        queue<T>::pop();
        return tmp;
    }

    void enqueue(const T& m_el) 
    {
        queue<T>::push(m_el);
    }
};

template<class T>
class BSTNode 
{
public:
	BSTNode()
	{
        m_el = 0;
        m_left = nullptr;
        m_right = nullptr;
	}

    BSTNode(const T& e, BSTNode<T>* l = nullptr, BSTNode<T> * r = nullptr)
    {
        m_el = e; 
        m_left = l; 
        m_right = r;
    }

	T m_el;
	BSTNode<T>* m_left;
	BSTNode<T>* m_right;
};

template<class T>
class BST 
{
public:
    BST()  { root = 0; }
    ~BST() { clear();  }

    void clear() 
    {
        clear(root);
        root = 0;
    }

	// 搜索,遞歸實現
	T* recursiveSearch(const T& m_el) const { return recursiveSearch(root, m_el); }
    // 搜索,非遞歸實現
    T* search(const T& m_el) const { return search(root, m_el); }

    // 前序遍歷,遞歸實現
    void preorder()  { preorder(root); }
    // 中序遍歷,遞歸實現
    void inorder()  { inorder(root); }
    // 後續遍歷,遞歸實現
    void postorder()  { postorder(root); }
    // 前序遍歷,非遞歸棧實現
    void iterativePreorder();
    // 中序遍歷,非遞歸棧實現
    void iterativeInorder();
    // 後序遍歷,非遞歸棧實現
    void iterativePostorder();
    // 前序遍歷,非遞歸Morris遍歷算法實現
    void MorrisPreorder();
    // 中序遍歷,非遞歸Morris遍歷算法實現
    void MorrisInorder();
    // 後序遍歷,非遞歸Morris遍歷算法實現
    void MorrisPostorder();

    // 廣度優先遍歷:從上到下,從左到右
    void breadthFirst();

    // 插入插入一個元素,非遞歸實現
    bool insert(const T&);
    // 插入插入一個元素,遞歸實現
    bool recursiveInsert(const T& m_el) { recursiveInsert(root, m_el); }

    // 查找合併刪除
    void findAndDeleteByMerging(const T&);
    // 查找複製刪除
    void findAndDeleteByCopying(const T&);

protected:
    BSTNode<T>* root;
    void clear(BSTNode<T>*);
    // 插入插入一個元素,遞歸實現
    bool recursiveInsert(BSTNode<T>*&, const T&);
    // 搜索(查找),非遞歸實現
    T* search(BSTNode<T>*, const T&) const;
    // 搜索(查找),遞歸實現
    T* recursiveSearch(BSTNode<T>*, const T&) const;
    // 前序遍歷,遞歸實現
    void preorder(BSTNode<T>*);
    // 中序遍歷,遞歸實現
    void inorder(BSTNode<T>*);
    // 後序遍歷,遞歸實現
    void postorder(BSTNode<T>*);
    // 複製刪除
    void deleteByCopying(BSTNode<T>*&);
    // 合併刪除
    void deleteByMerging(BSTNode<T>*&);
    // 訪問節點
    virtual void visit(BSTNode<T>* p) { cout << p->m_el << ' '; }
};

template<class T>
void BST<T>::clear(BSTNode<T>* p) 
{
    if (p != 0) 
    {
        clear(p->m_left);
        clear(p->m_right);
        delete p;
    }
}

// 搜索(查找),遞歸實現
template<class T>
T* BST<T>::recursiveSearch(BSTNode<T>* p, const T& m_el) const 
{
    if (p != 0)
    {
        if (m_el == p->m_el)
            return &p->m_el;
        else if (m_el < p->m_el)
            return recursiveSearch(p->m_left, m_el);
        else 
            return recursiveSearch(p->m_right, m_el);
    }
    else
        return 0;
}

// 搜索(查找),非遞歸實現
template<class T>
T* BST<T>::search(BSTNode<T>* p, const T& m_el) const 
{
    while (p != 0)
    {
        if (m_el == p->m_el)
            return &p->m_el;
        else if (m_el < p->m_el)
            p = p->m_left;
        else 
            p = p->m_right;
    }

    return 0;
}

// 前序遍歷,遞歸實現
template<class T>
void BST<T>::preorder(BSTNode<T>* p)
{
	if (p != 0)
	{
        visit(p);
        preorder(p->m_left);
        preorder(p->m_right);
	}
}

// 中序遍歷,遞歸實現
template<class T>
void BST<T>::inorder(BSTNode<T>* p) 
{
    if (p != 0) 
    {
        inorder(p->m_left);
        visit(p);
        inorder(p->m_right);
    }
}

// 後序遍歷,遞歸實現
template<class T>
void BST<T>::postorder(BSTNode<T>* p) 
{
    if (p != 0) 
    {
        postorder(p->m_left);
        postorder(p->m_right);
        visit(p);
    }
}

// 前序遍歷,非遞歸棧實現
template<class T>
void BST<T>::iterativePreorder() 
{
    Stack<BSTNode<T>*> travStack;
    BSTNode<T>* p = root;
    if (p != 0) 
    {
        travStack.push(p);
        while (!travStack.empty())
        {
            p = travStack.pop();
            visit(p);
            if (p->m_right != 0)
                travStack.push(p->m_right);

            if (p->m_left != 0)            
                travStack.push(p->m_left); 
        }
    }
}

// 中序遍歷,非遞歸棧實現
template<class T>
void BST<T>::iterativeInorder() 
{
    Stack<BSTNode<T>*> travStack;
    BSTNode<T>* p = root;
    while (p != nullptr) 
    {
        while (p != nullptr)
        {                 
            if (p->m_right)                
                travStack.push(p->m_right); 

            travStack.push(p);
            p = p->m_left;
        }

        p = travStack.pop();             
        while (!travStack.empty() && p->m_right == nullptr)
        { 
            visit(p);                                
            p = travStack.pop();
        }

        visit(p);                       
        if (!travStack.empty())          
            p = travStack.pop();
        else 
            p = nullptr;
    }
}

// 後序遍歷,非遞歸棧實現
template<class T>
void BST<T>::iterativePostorder() 
{
    Stack<BSTNode<T>*> travStack;
    BSTNode<T>* p = root, * q = root;
    while (p != nullptr) 
    {
        for (; p->m_left != nullptr; p = p->m_left)
            travStack.push(p);

        while (p->m_right == nullptr || p->m_right == q)
        {
            visit(p);
            q = p;
            if (travStack.empty())
                return;

            p = travStack.pop();
        }
        travStack.push(p);
        p = p->m_right;
    }
}

// 前序遍歷,非遞歸Morris遍歷算法實現
template<class T>
void BST<T>::MorrisPreorder() 
{
    BSTNode<T>* p = root, * tmp;
    while (p != nullptr) 
    {
        if (p->m_left == nullptr)
        {
            visit(p);
            p = p->m_right;
        }
        else 
        {
            tmp = p->m_left;
            while (tmp->m_right != nullptr && tmp->m_right != p)
                tmp = tmp->m_right;   

            if (tmp->m_right == nullptr)
            {  
                visit(p);         
                tmp->m_right = p;    
                p = p->m_left;        
            }
            else 
            {                   
                tmp->m_right = nullptr;    
                p = p->m_right;       
            }                        
        }
    }
}

// 中序遍歷,非遞歸Morris遍歷算法實現
template<class T>
void BST<T>::MorrisInorder() 
{
    BSTNode<T>* p = root, * tmp;
    while (p != 0)
    {
        if (p->m_left == 0) 
        {
            visit(p);
            p = p->m_right;
        }
        else 
        {
            tmp = p->m_left;
            while (tmp->m_right != 0 && tmp->m_right != p)  
                tmp = tmp->m_right;   
                
            if (tmp->m_right == 0) 
            {   
                tmp->m_right = p;    
                p = p->m_left;       
            }
            else 
            {                   
                visit(p);      
                tmp->m_right = 0;    
                p = p->m_right;      
            }                      
        }
    }
}

// 後序遍歷,非遞歸Morris遍歷算法實現
template<class T>
void BST<T>::MorrisPostorder() 
{
    BSTNode<T>* p = new BSTNode<T>(), * tmp, * q, * r, * s;
    p->m_left = root;
    while (p != 0)
    {
        if (p->m_left == 0)
            p = p->m_right;
        else
        {
            tmp = p->m_left;
            while (tmp->m_right != 0 && tmp->m_right != p)  
                tmp = tmp->m_right;   

            if (tmp->m_right == 0) 
            {   
                tmp->m_right = p;     
                p = p->m_left;        
            }
            else
            {             
                for (q = p->m_left, r = q->m_right, s = r->m_right;
                    r != p; q = r, r = s, s = s->m_right)
                    r->m_right = q;

                for (s = q->m_right; q != p->m_left;
                    q->m_right = r, r = q, q = s, s = s->m_right)
                    visit(q);

                visit(p->m_left);    
                tmp->m_right = 0;     
                p = p->m_right;      
            }                   
        }
    }
}

// 廣度優先遍歷:從上到下,從左到右
template<class T>
void BST<T>::breadthFirst() 
{
    Queue<BSTNode<T>*> queue;
    BSTNode<T>* p = root;
    if (p != 0) 
    {
        queue.enqueue(p);
        while (!queue.empty()) 
        {
            p = queue.dequeue();
            visit(p);
            if (p->m_left != 0)
                queue.enqueue(p->m_left);
            if (p->m_right != 0)
                queue.enqueue(p->m_right);
        }
    }
}

// 插入插入一個元素,非遞歸實現
template<class T>
bool BST<T>::insert(const T& m_el) 
{
    BSTNode<T>* p = root, * prev = 0;
    while (p != 0) 
    {  
        prev = p;
        if (m_el < p->m_el)
            p = p->m_left;
        else if (m_el > p->m_el)
            p = p->m_right;
        else
        {
            cout << "BST<T>::insert 插入相同的數據,插入失敗" << endl;
            return false;
        }
    }

    if (root == 0)    
        root = new BSTNode<T>(m_el);
    else if (m_el < prev->m_el)
        prev->m_left = new BSTNode<T>(m_el);
    else 
        prev->m_right = new BSTNode<T>(m_el);

	return true;
}

// 插入插入一個元素,遞歸實現
template<class T>
bool BST<T>::recursiveInsert(BSTNode<T>*& p, const T& m_el) 
{
    if (p == 0)
        p = new BSTNode<T>(m_el);
    else if (m_el < p->m_el)
        recursiveInsert(p->m_left, m_el);
    else if (m_el > p->m_el)
        recursiveInsert(p->m_right, m_el);
	else
    {
        cout << "BST<T>::recursiveInsert 插入相同的數據,插入失敗" << endl;
        return false;
    }
    
	return true; 
}


// 查找合併刪除
template<class T>
void BST<T>::findAndDeleteByMerging(const T& m_el)
{
    BSTNode<T>* p = root, * prev = 0;
    while (p != 0 && p->m_el != m_el)
    {
        prev = p;
        if (m_el < p->m_el)
            p = p->m_left;
        else
            p = p->m_right;
    }

    if (p != 0 && p->m_el == m_el)
    {
        if (p == root)
            deleteByMerging(root);
        else if (prev->m_left == p)
            deleteByMerging(prev->m_left);
        else
            deleteByMerging(prev->m_right);
    }
    else if (root != 0)
        cout << "m_el " << m_el << " is not in the tree\n";
    else 
        cout << "the tree is empty\n";
}

// 查找合併刪除
template<class T>
void BST<T>::deleteByMerging(BSTNode<T>*& node)
{
    if (node == nullptr)
        return;

    BSTNode<T>* tmp = node;
    if (node->m_right == nullptr)           // node 沒有右節點
        node = node->m_left;
    else if (node->m_left == nullptr)       // node 沒有左節點
        node = node->m_right;
    else
    {
        tmp = node->m_left;
        while (tmp->m_right != nullptr)
            tmp = tmp->m_right;

        tmp->m_right = node->m_right;
        tmp = node;
        node = node->m_left;
    }

    delete tmp;
}

// 查找複製刪除
template<class T>
void BST<T>::findAndDeleteByCopying(const T& m_el) 
{
    BSTNode<T>* p = root, * prev = 0;
    while (p != 0 && p->m_el != m_el) 
    {
        prev = p;
        if (m_el < p->m_el)
            p = p->m_left;
        else 
            p = p->m_right;
    }

    if (p != 0 && p->m_el == m_el)
    {
        if (p == root)
            deleteByCopying(root);
        else if (prev->m_left == p)
            deleteByCopying(prev->m_left);
        else
            deleteByCopying(prev->m_right);
	}
    else if (root != 0)
        cout << "m_el " << m_el << " is not in the tree\n";
    else 
        cout << "the tree is empty\n";
}

// 查找複製刪除
template<class T>
void BST<T>::deleteByCopying(BSTNode<T>*& node) 
{
    if (node == nullptr)
        return;
	
    BSTNode<T>* previous, * tmp = node;
    if (node->m_right == nullptr)                  // node 沒有右節點
        node = node->m_left;
    else if (node->m_left == nullptr)              // node 沒有左節點
        node = node->m_right;
    else 
    {
        tmp = node->m_left;							// node 有左、右節點
        previous = node;                   
        while (tmp->m_right != nullptr)
        {         
            previous = tmp;
            tmp = tmp->m_right;
        }

        node->m_el = tmp->m_el;                
        if (previous == node)
            previous->m_left = tmp->m_left;
        else 
            previous->m_right = tmp->m_left;   
    }

    delete tmp;                            
}

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章