c++學習筆記—二叉樹基本操作的實現
阿新 • • 發佈:2018-12-24
用c++語言實現的二叉樹基本操作,包括二叉樹的建立、二叉樹的遍歷(包括前序、中序、後序遞迴和非遞迴演算法)、求二叉樹高度,計數葉子節點數、計數度為1的節點數等基本操作。
IDE:vs2013
具體實現程式碼如下:
構建二叉樹示意圖為:#include "stdafx.h" #include <malloc.h> #include <stack> #include <iostream> #define MAXSIZE 100 using namespace std; typedef struct node //二叉樹結構體 { int data; struct node *lchild; struct node *rchild; }Bnode,*BTree; BTree CreateBinaryTree(BTree &tree){ //建立二叉樹 int inputdata; cin >> inputdata; if (-1 == inputdata) { tree = NULL; } else { if (!(tree = (Bnode*)malloc(sizeof(Bnode)))) { cout<<"ERROR"; } tree->data = inputdata; tree->lchild=CreateBinaryTree(tree->lchild); tree->rchild=CreateBinaryTree(tree->rchild); } return tree; } void preorderTraverse(BTree tree) //遞迴前序遍歷 { if (tree != NULL) { cout<<tree->data; } if (tree->lchild != NULL) { preorderTraverse(tree->lchild); } if (tree->rchild) { preorderTraverse(tree->rchild); } } void preorderTraverse2(BTree tree) { ////////////////////////////////////////////////////////////////////////// // 非遞迴前序 // 根據前序遍歷訪問的順序,優先訪問根結點, // 然後再分別訪問左孩子和右孩子。 // 即對於任一結點,其可看做是根結點,因此可以直接訪問,訪問完之後, // 若其左孩子不為空,按相同規則訪問它的左子樹;當訪問其左子樹時, // 再訪問它的右子樹。因此其處理過程如下: // ////////////////////////////////////////////////////////////////////////// stack<BTree> s; if (!tree) { cout << "空樹" << endl; return; } while (tree || !s.empty()) { while (tree) { s.push(tree); cout << tree->data; tree = tree->lchild; } tree = s.top(); s.pop(); tree = tree->rchild; } } void inorderTraverse(BTree tree) //遞迴中序遍歷 { if (tree->lchild) { inorderTraverse(tree->lchild); } cout << tree->data; if (tree->rchild) { inorderTraverse(tree->rchild); } } void inorderTraverse2(BTree tree) { ////////////////////////////////////////////////////////////////////////// // 非遞迴中序遍歷 // 根據中序遍歷的順序,對於任一結點,優先訪問其左孩子, // 而左孩子結點又可以看做一根結點,然後繼續訪問其左孩子結點, // 直到遇到左孩子結點為空的結點才進行訪問, // 然後按相同的規則訪問其右子樹。 // 因此其處理過程如下: // /////////////////////////////////////////////////////////////////////////// stack<BTree> s; if (!tree) { cout << "空樹" << endl; return; } while (tree || !s.empty()) { while (tree) { s.push(tree); tree = tree->lchild; } tree = s.top(); s.pop(); cout << tree->data; tree = tree->rchild; } } void postoderTraverse(BTree tree) //遞迴後序遍歷 { if (tree->lchild) { postoderTraverse(tree->lchild); } if (tree->rchild) { postoderTraverse(tree->rchild); } cout << tree->data; } void postoderTraverse2(BTree tree) { ////////////////////////////////////////////////////////////////////////// // 非遞迴後序遍歷 // 要保證根結點在左孩子和右孩子訪問之後才能訪問, // 因此對於任一結點P,先將其入棧。如果P不存在左孩子和右孩子, // 則可以直接訪問它;或者P存在左孩子或者右孩子, // 但是其左孩子和右孩子都已被訪問過了,則同樣可以直接訪問該結點。 // 若非上述兩種情況,則將P的右孩子和左孩子依次入棧, // 這樣就保證了每次取棧頂元素的時候,左孩子在右孩子前面被訪問, // 左孩子和右孩子都在根結點前面被訪問。 ////////////////////////////////////////////////////////////////////////// stack<BTree> s; BTree cur; //當前結點 BTree pre = NULL; //前一次訪問的結點 s.push(tree); while (!s.empty()) { cur = s.top(); if ((cur->lchild == NULL&&cur->rchild == NULL) ||(pre != NULL && (pre == cur->lchild || pre == cur->rchild))) { cout << cur->data; //如果當前結點沒有孩子結點或者孩子節點都已被訪問過 s.pop(); pre = cur; } else { if (cur->rchild != NULL) s.push(cur->rchild); if (cur->lchild != NULL) s.push(cur->lchild); } } } int Depth(BTree T) //求二叉樹的深度 { int dep = 0, depl, depr; if (!T) dep = 0; else { depl = Depth(T->lchild); depr = Depth(T->rchild); dep = 1 + (depl>depr ? depl : depr); } return dep; } int sumLeaf(BTree tree) //求葉子節點的個數 { int sum = 0, m, n; if (tree) { if ((!tree->lchild) && (!tree->rchild)) sum++; m = sumLeaf(tree->lchild); sum += m; n = sumLeaf(tree->rchild); sum += n; } return sum; } int numnSinglePoint(BTree tree ) //統計度為1的節點數目 { int sum = 0, m, n; if (tree) { if ((tree->lchild!=NULL) && (tree->rchild == NULL)) sum++; if ((tree->lchild == NULL) && (tree->rchild != NULL)) sum++; m = numnSinglePoint(tree->lchild); sum += m; n = m = numnSinglePoint(tree->rchild); sum += n; } return sum; } int _tmain(int argc, _TCHAR* argv[]) { BTree t; t= CreateBinaryTree(t); cout<<endl<<"非遞迴前序遍歷:"; preorderTraverse2(t); cout << endl<<"----------------------"<<endl; cout << "遞迴前序遍歷:"; preorderTraverse(t); cout << endl << "---------------------"<<endl; cout << "非遞迴中序遍歷:"; inorderTraverse2(t); cout << endl << "---------------------"<<endl; cout << "遞迴中序遍歷:"; inorderTraverse(t); cout << endl << "---------------------"<<endl; cout << "非遞迴後序遍歷:"; postoderTraverse2(t); cout << endl << "---------------------"<<endl; cout << "遞迴後序遍歷:"; postoderTraverse(t); cout << endl << "----------------------"<<endl; cout << "連結串列深度為:"<<Depth(t); cout << endl << "----------------------"<<endl; cout << "連結串列的葉子節點個數為:" << sumLeaf(t); cout << endl << "----------------------"<<endl; cout << "連結串列中度為1的節點數目為:" << numnSinglePoint(t) << endl; return 0; }
執行程式結果為: