1. 程式人生 > >常用資料結構-二叉樹的鏈式儲存、建立和遍歷

常用資料結構-二叉樹的鏈式儲存、建立和遍歷

1. 鏈式二叉樹簡介

        二叉樹是資料結構——樹的一種,一般定義的樹是指有一個根節點,由此根節點向下分出數個分支結點,以此類推以至產生一堆結點。樹是一個具有代表性的非線性資料結構,所謂的非線性,就是指不再是一對一,而是一對多,不過我覺得其實無論是線性還是非線性,無非就是指標指向的物件個數而已,畢竟雙向連結串列中,一個結點也是指向了兩個結點,這是不是也是一對多呢?由此觀之,資料結構就是結點的不同組合方式而已。

        二叉樹是指,任意一個結點的子節點最多有兩個,具體還分為滿二叉樹(除了最下層的結點,其餘結點的度都為2)、完全二叉樹(滿二叉樹轉化而來,留左不留右)等,還具有一些計算上的性質,如計算滿二叉樹的結點等。二叉樹也是樹中最容易表達的種類,因此非二叉樹、森林等都可以轉化為二叉樹進行儲存。

        用鏈式儲存二叉樹是因為二叉樹某些結點可能為空,如果採用陣列儲存,可能造成空間的浪費,其實對於滿二叉樹,完全二叉樹而言採用陣列儲存可能更好。

2. 鏈式二叉樹的建立

      1. 二叉樹的建立  

       1. 建立結點結構體,每個結點包括一個數據域和左右子結點的指標域

       2. 建立節點的左右子結點

       3. 對2中建立的子結點再重複第2步,以此類推直到結束

const int MAXSIZE = 200;

template <class T>
/*typedef struct Node
{
    T data;
    struct Node* leftChild;
    struct Node* rightChild;
}*BitTree, BitNode;*/
struct Node
{
    T data;
    struct Node<T>* leftChild;
    struct Node<T>* rightChild;
};


template <class T>
class myBitTree
{
public:
    struct Node<T>* pRootNode;

    //Node<T>* rootNode;

    myBitTree();
    //BitNode* CreateBitTree();
    Node<T>* CreateBitTree();
    void PreOrderTraversal(Node<T>* node);
    void InOrderTraversal(Node<T>* node);
    void PostOrderTraversal(Node<T>* node);
};

template <class T>
myBitTree<T>::myBitTree()
{
    pRootNode = new Node<T>;
    pRootNode = CreateBitTree();
}

template <class T>
Node<T>* myBitTree<T>::CreateBitTree()
{
    T ch;
    cin>>ch;
    Node<T>* pNode = new Node<T>;;//產生新的結點空間
    if ('#' == ch)//錄入“#”表示空結點,非空則遞迴迴圈產生子結點
    {
        pNode = nullptr;
        cout<<"Haha."<<endl;
    }
    else
    {
        //pNode = new Node<T>;

        pNode->data = ch;
        cout<<pNode->data;
        pNode->leftChild = CreateBitTree();
        pNode->rightChild = CreateBitTree();
    }
    return pNode;
}

       2. 二叉樹的遍歷

        二叉樹的遍歷分為前序中序和後序,所謂的前中後就是根節點的遍歷位置(此處的根節點是相對的),具體而言,前序遍歷就是指先訪問根結點,再訪問根節點的左子樹,最後訪問根節點的右子樹,其中訪問左右子樹的時候,依舊按照“中-左-右”的順序訪問。同理,中序遍歷即“左中右”,後序遍歷即“左右中”,說起來複雜,實現起來非常簡單,程式碼如下:

template <class T>
void myBitTree<T>::PreOrderTraversal(Node<T>* node)
{
    if (node)
    {
        cout<<node->data<<endl;
        //cout<<"1"<<endl;
        //cout<<node->rightChild->data;
        PreOrderTraversal(node->leftChild);
        PreOrderTraversal(node->rightChild);
    }
}

template <class T>
void myBitTree<T>::InOrderTraversal(Node<T>* node)
{
    if (node)
    {
        InOrderTraversal(node->leftChild);
        cout<<node->data<<endl;
        //cout<<"1"<<endl;
        //cout<<node->rightChild->data;

        InOrderTraversal(node->rightChild);
    }
}

template <class T>
void myBitTree<T>::PostOrderTraversal(Node<T>* node)
{
    if (node)
    {
        PostOrderTraversal(node->leftChild);
        PostOrderTraversal(node->rightChild);
        cout<<node->data<<" ";
        //cout<<"1"<<endl;
        //cout<<node->rightChild->data;
    }
}


3. 注意的問題

    1. 寫了這個之後其實發現資料結構並不是很難的東西,稍微熟練一些就好了,畢竟不是讓我去想出這些結構,而是去用現成的~

    2. 二叉樹的建立和遍歷都用到了遞迴