常用資料結構-二叉樹的鏈式儲存、建立和遍歷
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. 二叉樹的建立和遍歷都用到了遞迴