1、樹的存儲:
注意:樹的深度是從根節點開始(其深度為1)自頂向下逐層累加的,而高度是從葉節點開始(其高度為1)自底向上逐層累加的。雖然樹的深度和高度一樣,但是具體到樹的某個節點,其深度和高度是不一樣的。我的理解是:非根非葉結點的深度是從根節點數到它的,高度是從葉節點數到它的。
二叉樹的存儲:1、數組存儲(此方法適合完全二叉樹的存儲)
2、鏈表存儲(可分為二叉鏈表,三叉鏈表)結構如下:
2、 使用二叉鏈表實現二叉樹
測試用例:
int a[10] = { 1, 2, '#', '#', 3, 4, '#', '#', 5, 6 };//其中用'表示空'
按前序遍歷的算法重建出二叉樹為:(先創建根節點,再創建左子樹,后創建右子樹)
代碼實現:
BinaryTree<T>* _CreateBinaryTree(const T *a,size_t size, size_t&index) { assert(a); BinaryTreeNode<T> *node = new BinaryTreeNode<T> (a[index]); if (index < size&&a[index++] != '#') { node->_left = _CreateBinaryTree(a, size, ++index); node->_right = _CreateBinaryTree(a, size, ++index); } else
{
return NULL;
}
return node; }
3、二叉樹的遍歷
以上圖的二叉樹為例:
1-a、先序遍歷(由於二叉樹的結構具有遞歸的特性可以采用遞歸的方式遍歷)
void _PrevOrder(BinaryTreeNode<T>* root) { if (root) { cout<<root->_data<<" "; _PrevOrder(root->_left); _PrevOrder(root->_right); } else return; }
1-b、二叉樹的非遞歸先序遍歷
思想:1、可以采用棧先進先出的原則:先使根節點入棧,棧不為空打印棧頂元素,彈出棧頂元素,
2、在使棧頂元素的不為空右子樹入棧,再使棧頂元素的不為空左子樹入棧
3、 再按1、2進行判斷直至棧為空退出
void PrevOrder_NonR(BinaryTreeNode<T> *_root) { if (_root==NULL) { return; } stack<BinaryTreeNode<T>*> s1; s1.push(_root); while (!s1.empty()) { BinaryTreeNode<T> *top=s1.top(); cout<<top->_data<<" "; s1.pop(); if (top->_right) { s1.push(top->_right); } if (top->_left) { s1.push(top->_left); } } cout<<endl; }
2-a、二叉樹的中序遍歷(遞歸)
void _InOrder(BinaryTreeNode<T>* root) { if (root) { _InOrder(root->_left); cout<<root->_data<<" "; _InOrder(root->_right); } else { return; } }
2-b、二叉樹的中序遍歷非遞歸
思想:中序遍歷是先遍歷左子樹,再遍歷根節點,后遍歷右子樹
1、使cur指向根節點,使cur->_left入棧直至cur為空(定義cur是為了指向當前遍歷的節點)
2、若棧不為空,打印棧頂元素,使cur指向棧頂元素的右子樹(當前的棧頂元素也就是某一個樹的根節點,但其右子樹還未遍歷所以使cur指向其右子樹)
3-a、若棧不為空,前一步棧頂元素的右子樹為空,直接打印當前棧頂元素也就是前一步棧頂元素的根節點
3-b、若棧不為空,前一步棧頂元素的右子樹不為空,使cur指向的右子樹入棧
4、在按照2,3的步驟循環,直至cur和棧為空時結束
//非遞歸中序 void InOrder_NonR(BinaryTreeNode<T> *root) { stack<BinaryTreeNode<T>*> s1; BinaryTreeNode<T>* cur=_root; while (cur||!s1.empty()) { while (cur) { s1.push(cur); cur=cur->_left; } if (!s1.empty()) { BinaryTreeNode<T>* top=s1.top(); cout<<top->_data<<" "; s1.pop(); cur=top->_right; } } cout<<endl; }
3-a二叉樹的后續遍歷(遞歸)
void _PostOrder(BinaryTreeNode<T>* root) { if (root) { _PostOrder(root->_left); _PostOrder(root->_right); cout<<root->_data<<" "; } else { return; } }